Двойная проверка блокировки не является проблемой из-за неявного барьера памяти?
Я рассматриваю фрагмент кода и заметил двойную проверку реализации блокировки для установки блокировки сеанса:
Lock lock = getLock(mySession);
if (lock == null) {
synchronized (myService.class) {
lock = getLock(mySession);
if (lock == null) {
lock = new ReentrantLock();
setLock(mySession, lock);
}
}
}
Вместе с этим фрагментом кода был комментарий, в котором говорилось, что разработчик предположил, что для атрибута существует барьер памяти: ЦП очистит свои кэши и напрямую прочитает значение из основной памяти.
Является ли это хорошим предположением, или все же лучше будет определить "блокировку" как изменчивую, чтобы гарантировать ее?
1 ответ
Предполагая, что ваш код ограничен блоком или методом:
public void mymethod() {
//...
Lock lock = getLock(mySession);
if (lock == null) {
synchronized (myService.class) {
lock = getLock(mySession);
if (lock == null) {
lock = new ReentrantLock();
setLock(mySession, lock);
}
}
}
//...
}
Вопрос двойной проверки к нему вообще не относится, так как lock
является локальной переменной (размещенной в стеке потока), поэтому каждый поток видит свою собственную копию, и нет параллельного доступа к ней (что является существенным предварительным условием для проблем двойной проверки).