Java CopyOnWrite中volatile字段的用法

Java CopyOnWrite中volatile字段的用法,java,concurrency,copy-on-write,Java,Concurrency,Copy On Write,写时复制的“标准”代码如下所示: ... private volatile SomeClass object; private ReentrantLock lock = new ReentrantLock(); public change (...) { lock.lock(); //set lock on write try { SomeClass newObject = new SomeClass(); //do something wi

写时复制的“标准”代码如下所示:

...
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修饰符。我错了吗

据我所知,对象引用赋值操作是原子的

是的,但不是关于原子赋值,而是关于这个变量的值对于读取这个变量的所有线程都是相同的

它实际上是关于原子变量访问的,而不是关于原子变量分配的。

来自(emphasis mine):

原子操作不能交错,因此它们可以在不担心线程干扰的情况下使用。然而,这并不能消除同步原子操作的所有需要,因为内存一致性错误仍然是可能的。使用易失性变量可以降低内存一致性错误的风险,因为对易失性变量的任何写入都会与该变量的后续读取建立“发生在之前”的关系。这意味着对易失性变量的更改对其他线程总是可见的


这是为其他线程提供可见性所必需的。如果没有
volatile,则引用分配可能仅对进行更改的线程可见。如果get方法在用于更改字段的同一个锁下工作,则不需要它。谢谢!这是我没有考虑的方面