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方法在用于更改字段的同一个锁下工作,则不需要它。谢谢!这是我没有考虑的方面