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

Как было отмечено, класс Pair не приспособлен к работе с потоками, поскольку его инвариант (предположительно произвольный) требует равенства обоих переменных. Вдобавок, как мы уже видели в этой главе, операции инкремента небезопасны в отношении к потокам, и, так как ни один из методов не был объявлен как synchronized, мы не можем считать, что объект Pair останется неповрежденным в многопоточной программе.

Представьте, что вы получили готовый класс Pair, который должен работать в многопоточных условиях. Класс PairManager хранит объекты Pair и управляет любым доступом к ним. Заметьте, что единственными открытыми (public) методами являются getPair(), объявленный как synchronized, и абстрактный метод doTask(). Синхронизация этого метода будет осуществлена при его реализации.

this pm = pm.

}

public void run() {

while(true) {

pm checkCounter.i ncrementAndGet(); pm getPa>r() checkState(),

Структура класса PairManager, в котором часть функциональности базового класса реализуется одним или несколькими абстрактными методами, определенными производными классами, называется на языке паттернов проектирования «шаблонным методом». Паттерны проектирования позволяют инкапсулировать изменения в коде — здесь изменяющаяся часть представлена методом increment(). В классе PairManagerl метод increment() полностью синхронизирован, в то время как в классе PairManager2 только часть его была синхронизирована посредством синхронизируемой блокировки. Обратите внимание еще раз, что ключевые слова synchronized не являются частью сигнатуры метода и могут быть добавлены во время переопределения.

Метод store() добавляет объект Pair в синхронизированный контейнер Array-List, поэтому операция является потоково-безопасной. Следовательно, в защите он не нуждается, поэтому его вызов размещен за пределами синхронизируемого блока.

Класс PairManipulator создается для тестирования двух разновидностей Pair-Manager: метод increment() вызывается в задаче в то время, как в другой задаче работает PairChecker. Метод main() создает два объекта PairManipulator и дает им поработать в течение некоторого времени, после чего выводятся результаты по каждому PairManipulator.

Для создания критических секций также можно воспользоваться явно созданными объектами Lock:

//: concurrency/ExplicitCriticalSection.java

// Использование объектов Lock для создания критических секций.

package concurrency;

import java.util.concurrent.locks.*;

// Синхронизация целого метода: class ExplicitPairManagerl extends PairManager { private Lock lock = new ReentrantLockO; public synchronized void incrementO { lock lockO; try {

p.incrementXO; p. incrementYO; store(getPairO); } finally {

lock.unlock О;

}

}

}

// Использование критической секции: class ExplicitPairManager2 extends PairManager { private Lock lock = new ReentrantLockO: public void incrementO { Pair temp; lock.lockO: try {

p.incrementXO;

р incrementYO. temp = getPairO. } finally {

lock unlock О,

}

store(temp),

public class ExplicitCriticalSection {

public static void main(String[] args) throws Exception { PairManager

pmanl = new ExplicitPairManagerK), pman2 = new ExplicitPairManager2(), CriticalSection.testApproaches(pmanl, pman2);

}

} /* Output

pml. Pair: x: 15, у 15 checkCounter = 174035 pm2: Pair- x- 16, у 16 checkCounter = 2608588 *///.-

В программе создаются новые типы PairManager с явным использованием объектов Lock. ExplicitPairManager2 демонстрирует создание критической секции с использованием объекта Lock; вызов store() находится вне критической секции.

Синхронизация по другим объектам

Блоку synchronized необходимо передать объект, который будет использоваться для синхронизации. Чаще всего наиболее естественно передавать текущий объект, для которого был вызван метод synchronized(this), и именно такой подход применен в классе PairManager2. Таким образом, при входе в синхронизируемый блок другие синхронизированные методы объекта вызвать будет нельзя. Действие синхронизации по this фактически заключается в сужении области синхронизации.

Иногда вам нужно что-то иное, и в таких ситуациях вы создаете отдельный объект и выполняете синхронизацию, привлекая его. В таких случаях необходимо позаботиться о том, чтобы все операции синхронизировались по одному и тому же объекту. Следующий пример показывает, как два потока входят в объект, когда методы этого объекта синхронизированы различными блокировками:

У/ concurrency/SyncObject java // Синхронизация по другому объекту, import static net.mindview util.Print *;

class Dual Synch {

private Object syncObject = new Object О; public synchronized void f() {

for(int i = 0; i < 5; i++) { printCfO"); Thread.yieldO;

}

}

public void gO { продолжение &

synchronizedsyncObject) {

for(int i = 0; i < 5; i++) { printC'gO"); Thread.yieldO;

public class SyncObject {

public static void main(String[] args) {

final Dual Synch ds = new DualSynchO; new ThreadO {

public void run() { ds.fO;

}

}.startO; ds.gO;

}

} /* Output:

go

fO

go f() go fo go fo go f() *///:-

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

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

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