Использование изменчивого поля в CopyOnWrite

"Стандартный" код копирования при записи выглядит так:

...
private volatile SomeClass object;

private ReentrantLock lock = new ReentrantLock();

public change (...) {
    lock.lock(); //set lock on write
    try {
        SomeClass newObject  = new SomeClass();
        //do something with new object
        ...
        //set new object
        object = newObject;
    } finally {
        lock.unlock(); //release lock
    }
}

public Object getSomeField () {
    SomeClass obj = object;
    return obj.getSomeField();
}

Вопрос: почему поле, которое хранит ссылку на "защищенный от записи" объект, является изменчивым? (например, см. реализацию CopyOnWriteArrayList). Насколько я знаю, операция присвоения ссылки на объект является атомарной, поэтому похоже, что модификатор volatile не нужен. Я ошибаюсь здесь?


person bw_dev    schedule 17.07.2016    source источник
comment
Это необходимо для обеспечения видимости других потоков. Без volatile присвоение ссылки может быть видно только тому потоку, который внес изменение. Вам бы это не понадобилось, если бы метод get работал под той же блокировкой, которая используется для изменения поля.   -  person Andrew Logvinov    schedule 17.07.2016
comment
Спасибо! Это аспект, который я не принял во внимание   -  person bw_dev    schedule 17.07.2016


Ответы (2)


Насколько я знаю, операция присваивания ссылки на объект является атомарной.

Да, но volatile модификатор относится не к атомарному присваиванию, а о том, что значение этой переменной будет одинаковым для всех потоков, читающих эту переменную.

На самом деле речь идет о доступе к атомарным переменным, а не о назначении атомарных переменных.

person Aleksandr Podkutin    schedule 17.07.2016

Из "Atomic Access" в руководствах по Java (выделено мной) :

Атомарные действия нельзя чередовать, поэтому их можно использовать, не опасаясь интерференции потоков. Однако это не избавляет от необходимости синхронизировать атомарные действия, поскольку все еще возможны ошибки непротиворечивости памяти. Использование изменчивых переменных снижает риск ошибок согласованности памяти, поскольку любая запись в изменчивую переменную устанавливает связь "происходит до" с последующим чтением той же самой переменной. Это означает, что изменения изменчивой переменной всегда видны другим потокам.

person Andy Turner    schedule 17.07.2016