Читаем Философия Java3 полностью

Библиотека Java SE5 java.utiLconcurrent также содержит явный механизм управления мьютексами, определенный в java.util.concurrent.locks. Объект Lock можно явно создать в программе, установить или снять блокировку; правда, полученный код будет менее элегантным, чем при использовании встроенной формы. С другой стороны, он обладает большей гибкостью при решении некоторых типов задач. Вот как выглядит пример SynchronizedEvenGenerator.java с явным использованием объектов Lock:

II: concurrency/MutexEvenGenerator.java

// Предотвращение потоковых конфликтов с использованием мьютексов.

II {RunByHand}

import java.util.concurrent.locks.*;

public class MutexEvenGenerator extends IntGenerator { private int currentEvenValue = 0, private Lock lock = new ReentrantLockO; public int nextO { lock lockO; try {

++currentEvenValue; Thread.yieldO; // Ускоряем сбой ++currentEvenValue; return currentEvenValue; } finally { продолжение ^

lock.unlockO,

}

}

public static void main(String[] args) {

EvenChecker test(new MutexEvenGeneratorO).

}

} /// ~

MutexEvenGenerator добавляет мьютекс с именем lock и использует методы lock() и unlock() для создания критической секции в next(). При использовании объектов Lock следует применять идиому, показанную в примере: сразу же за вызовом lock() необходимо разместить конструкцию try-finally, при этом в секцию finally включается вызов unlock() — только так можно гарантировать снятие блокировки.

Хотя try-finally требует большего объема кода, чем ключевое слово synchronized, явное использование объектов Lock обладает своими преимуществами. При возникновении проблем с ключевым словом synchronized происходит исключение, но вы не получите возможность выполнить завершающие действия, чтобы сохранить корректное состояние системы. При работе с объектами Lock можно сделать все необходимое в секции finally.

В общем случае использование synchronized уменьшает объем кода, а также радикально снижает вероятность ошибки со стороны программиста, поэтому явные операции с объектами Lock обычно выполняются только при решении особых задач. Например, с ключевым словом synchronized нельзя попытаться получить блокировку с неудачным исходом или попытаться получить блокировку в течение некоторого промежутка времени с последующим отказом — в подобных случаях приходится использовать библиотеку concurrent:

//: concurrency/AttemptLocking java

// Объекты Lock из библиотеки concurrent делают возможными

// попытки установить блокировку в течение некоторого времени

import java.util.concurrent *;

import java util concurrent.locks.*;

public class AttemptLocking {

private ReentrantLock lock = new ReentrantLockO;

public void untimedO {

boolean captured = lock.tryLockO, try {

System.out printlnCtryLockO: " + captured); } finally {

if(captured)

lock unlockO;

}

}

public void timedO {

boolean captured = false; try {

captured = lock tryLock(2, TimeUnit SECONDS); } catch(InterruptedException e) {

throw new RuntimeException(e);

}

try {

System out println("tryLock(2. TimeUnit SECONDS): " +

captured),

} finally {

if(captured)

lock unlockO,

}

}

public static void main(String[] args) {

final AttemptLocking al = new AttemptLocking(),

al untimedO. // True -- блокировка доступна al timedO. // True -- блокировка доступна // Теперь создаем отдельную задачу для установления блокировки new ThreadO {

{ setDaemon(true), } public void run() {

al lock lockO.

System.out printlnC'acquired");

}

} startO,

Thread yieldO, // Даем возможность 2-й задаче al untimedO; // False -- блокировка захвачена задачей al.timedO. // False -- блокировка захвачена задачей

}

} /* Output-tryLockO. true

tryLock(2, TimeUnit.SECONDS): true acquired

tryLockO false

tryLock(2, TimeUnit SECONDS)- false */// ~

Класс ReentrantLock делает возможной попытку получения блокировки с последующим отказом от нее. Таким образом, если кто-то уже захватил блокировку, вы можете отказаться от своих намерений (вместо того, чтобы дожидаться ее освобождения). В методе timed() делается попытка установления блокировки, которая может завершиться неудачей через 2 секунды (обратите внимание на использование класса Java SE5 TimeUnit для определения единиц времени). В main() отдельный объект Thread создается в виде безымянного класса и устанавливает блокировку, чтобы методы untimed() и timed() могли с чем-то конкурировать.

Атомарные операции и ключевое слово volatile

В дискуссиях, посвященных механизму потоков в Java, часто можно услышать такое утверждение: «Атомарные операции не требуют синхронизации». Атомарная операция — это операция, которую не может прервать планировщик потоков — если она начинается, то продолжается до завершения, без возможности переключения контекста (переключения выполнения на другой поток). Не полагайтесь на атомарность, она ненадежна и опасна — используйте ее вместо синхронизации только в том случае, если вы являетесь экспертом в области синхронизации или, по крайней мере, можете получить помощь от такого эксперта.

Перейти на страницу:

Похожие книги

Access 2002: Самоучитель
Access 2002: Самоучитель

В книге рассматривается широкий круг вопросов, связанных с использованием программной среды Access 2002, которая является составной частью пакета Office 2002 и предназначена для создания банка данных в самых различных предметных областях.Подробно описывается методика проектирования объектов базы данных (таблицы, формы, отчеты, страницы доступа к данным, запросы, модули).Детально обсуждаются вопросы создания интегрированной базы данных в единой среде Access 2002: формирование БД с нуля, конвертирование в программную среду баз данных, созданных в ином программном окружении – Clarion, FoxPro.Особое внимание уделяется формированию разнообразных запросов к интегрированной базе данных Access 2002 с использованием языков программирования SQL, VBA и макросов.Приводятся общие сведения о возможностях языка обмена данными между различными компьютерами и приложениями (XML). Описываются возможности использования гиперссылок, связывающих базу данных с другими программными продуктами. Объясняется, как можно работать с базой данных Access 2002 без установки ее на компьютер, используя технологию ODBC (Open Data Base Connectivity). В приложениях приводятся количественные параметры Access 2002 и связанная с этой СУБД терминология.Предлагаемая книга будет полезна специалистам, занимающимся практической разработкой банков данных и приложений на их основе, а также студентам вузов, изучающим информатику.

Павел Юрьевич Дубнов

Программирование, программы, базы данных / ОС и Сети / Книги по IT