Java内存模型中提到:当线程作为释放相关监视器的一部分退出同步块时,JMM要求将本地处理器缓存刷新到主内存。类似地,在进入同步块时,作为获取监视器的一部分,本地缓存将失效,以便后续读取将直接进入主内存,而不是本地缓存.。
那么,为什么在该代码中我必须将实例声明为易失性的,因为当第二个线程进入同步块时,将直接进入主内存?
public final class MySingleton {
private static MySingleton instance = null;
private MySingleton() { }
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
}我的意思是,当另一个线程进入同步块并进行第二次检查时,它应该从主存中更新,如前所述。
发布于 2012-03-13 09:45:21
比赛条件是:
instance == NULL并运行此代码instance = new MySingleton();。对instance.MySingleton的写入还没有。instance != NULL并开始处理instance != NULLB,现在正在处理一个它看不到的对象。使instance易失性解决了这个问题,因为JDK内存规范(如JDK5 )保证了对非易失性对象的写入不会因写入易失性对象而出现混乱。因此,任何看到instance != NULL的线程都必须看到实例本身。
发布于 2012-03-13 09:39:47
您必须声明它是不稳定的,否则不能保证两个对getInstance()的调用将返回同一个实例。
不能保证主内存将被访问,只有一个与缓存一致的值.也就是说,所有线程都会看到相同的值。
顺便说一句:你知道,它当然比需要的要复杂得多。你所需要的就是
public enum MySingleton {
INSTANCE;
}做同样的事。
https://stackoverflow.com/questions/9681407
复制相似问题