问题描述
我有一段代码看起来像这样:
class Creature {
private static long numCreated;
public Creature(){
synchronized(Creature.class){
numCreated ++;
}
}
public static long numCreated(){
return numCreated;
}
}
从我的理解, c> numCreated 不同步,如果Thread-A在下午1点创建 Creature ,并且Thread-B读取 numCreated )在下午2点, numCreated()可能返回0或1(即使线程A已经完成初始化对象在1.05pm) 。
所以我添加了同步到 numCreated() :
class Creature {
private static long numCreated;
public Creature(){
synchronized(Creature.class){
numCreated ++;
}
}
public static synchronized long numCreated(){//添加synchronized
return numCreated;
}
}
一切正常,除了我在想,if我将其修改为 Snippet C ,是 numCreated 仍正确同步?
class Creature {
private static volatile long numCreated; // addvolatile
public Creature(){
synchronized(Creature.class){
numCreated ++;
}
}
public static long numCreated(){// removesynchronized
return numCreated;
}
}
使用它保证一旦Thread-A在下午1:05完成对象创建,Thread-B对 numCreated()的调用肯定会返回 1 ?
class Creature { private static long numCreated; public Creature() { synchronized (Creature.class) { numCreated++; } } public static long numCreated() { return numCreated; } }
From my understanding, since reading of numCreated is not synchronized, if Thread-A creates a Creature at 1pm, and Thread-B reads numCreated() at 2pm, numCreated() may well have returned either 0 or 1 (even when Thread-A has finished initializing the object at 1.05pm).
So I added synchronized to numCreated():
:
class Creature { private static long numCreated; public Creature() { synchronized (Creature.class) { numCreated++; } } public static synchronized long numCreated() { // add "synchronized" return numCreated; } }
and all's well, except that I was thinking, if I modify it to Snippet C, is the variable numCreated still synchronized properly?
class Creature { private static volatile long numCreated; // add "volatile" public Creature() { synchronized (Creature.class) { numCreated++; } } public static long numCreated() { // remove "synchronized" return numCreated; } }
With Snippet C, is it guaranteed that as soon as Thread-A completes object creation at 1:05pm, Thread-B's call to numCreated() is sure to return 1 ?
So the answer is yes. The write of the volatile in the constructor happens before the read of the volatile in numCreated(). And since the non-atomic incrementation is still done in a synchronized block, the synchronization is alright (the incrementation is not atomic, but the write of the volatile long is).
这篇关于Java易失性变量在读取之前强加一个发生先前的关系吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!