[英]Does Java volatile variables impose a happens-before relationship before it is read?
我有一段看起来像这样的代码:
片段A:
class Creature {
private static long numCreated;
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static long numCreated() {
return numCreated;
}
}
根据我的理解,由于numCreated
读取不同步,如果Thread-A在下午1点创建一个Creature
,而Thread-B在下午2点读取numCreated()
,则numCreated()
可能返回0或1(即使在Thread-A时)已经在晚上1点05分完成了对象的初始化。
所以我添加了synchronized
到numCreated()
:
代码片段B :
class Creature {
private static long numCreated;
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static synchronized long numCreated() { // add "synchronized"
return numCreated;
}
}
并且一切都很好,除了我在想,如果我将它修改为Snippet C ,变量numCreated
仍然正确同步?
片段C:
class Creature {
private static volatile long numCreated; // add "volatile"
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static long numCreated() { // remove "synchronized"
return numCreated;
}
}
使用Snippet C ,可以保证一旦Thread-A在下午1:05完成对象创建,Thread-B对numCreated()
的调用肯定会返回1
吗?
PS:我知道在实际情况下我可能会使用AtomicLong
但这是出于学习目的
在每次后续读取同一字段之前,会发生对易失性字段的写入。 易失性字段的写入和读取具有与进入和退出监视器类似的内存一致性效果,但不需要互斥锁定。
所以答案是肯定的。 构造函数中volatile的写入发生在numCreated()
读取volatile之前。 并且由于非原子增量仍然在同步块中完成,因此同步是正常的(增量不是原子的,而是写入volatile的long)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.