我对volatile的理解是它确保始终从内存中读取值,所以据我所知,在下面的示例中,myObject
变量需要是volatile才能避免{NullPointerException
变量1}}被抚养:
private final Object lock = new Object();
private MyObject myObject = null;
//...
synchronized (lock) {
if (myObject == null) {
myObject = new MyObject();
}
myObject.blah();
// some other stuff that I want synchronized
}
myObject
仅在同步块中触及。 lock
仅用于同步该块。
这是对的吗?
稍微改写一下,我的问题是......想象两个线程正在击中该代码。第一个线程锁定并设置myObject,调用.blah()
以及synchronized块中的任何其他代码并退出synchronized块。这允许线程2进入同步块。如果不将myObject
设置为易变,是否仍有可能将myObject == null
评估为true
?
答案 0 :(得分:3)
synchronized
块将确保其他线程可以看到内存更新。没有必要使myObject
易变。
来自Intrinsic Locks and Synchronization:
当一个线程释放一个内部锁时,就会发生一次 在该行动与任何后续行动之间建立关系 获得同样的锁。
答案 1 :(得分:0)
我认为这里不需要volatile,因为进入synchronized块的每个线程都在检查myObject引用,所以当第一个线程进入块时,myObject应该是即时的,其他线程通过检查是myObject而不是null。对我来说看起来不错。
编辑:我希望只有这一个块你想要使用myObect参考,并且你不会在同步块之前或之后更改这个参考。