Немного покопавшись в коде, я нашел примеры обоих способов от того же автора, Дуга Ли:
LinkedBlockingDeque
(начиная с JDK 1.6) использует метод "прямого доступа".
CopyOnWriteArrayList
(начиная с JDK 1.5) использует метод "локальной переменной".
Есть больше примеров для каждой идиомы в java.util.concurrent
, но кажется, что для каждого класса был выбран непротиворечивый стиль.
Обратите внимание, что во всех соответствующих случаях поле lock
было объявлено final
. Это самая важная часть, потому что семантика модели памяти для конечных полей немного особенная в JVM (см. JLS) .
Опираясь на это: получение локальной копии или нет не влияет на правильность многопоточности.
Также обратите внимание, что Dough Lea выбрала более короткий стиль в новом коде (как показано в примерах). Так что, возможно, идиома «взять локальную копию» - это то, что осталось от дней до того, как java.util.concurrent
был частью JDK и до того, как модель памяти JVM была принята соответствующим образом. Я предполагаю, что код до этого принятия мог бы выглядеть так:
public void op(){
ReentrantLock lock = getLock();
lock.lock();
try {
realOp();
} finally {
lock.unlock();
}
}
где getLock()
содержал грубую многопоточную безопасную логику.