Представьте, что вы получили готовый класс 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() находится вне критической секции.