Двойная проверка блокировки не является проблемой из-за неявного барьера памяти?

Я рассматриваю фрагмент кода и заметил двойную проверку реализации блокировки для установки блокировки сеанса:

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 является локальной переменной (размещенной в стеке потока), поэтому каждый поток видит свою собственную копию, и нет параллельного доступа к ней (что является существенным предварительным условием для проблем двойной проверки).

Другие вопросы по тегам