java在同步之前更新内存?
Java内存模型中提到:当线程退出同步块作为释放相关监视器的一部分时,JMM要求将本地处理器缓存刷新到主存。类似地,作为进入同步块时获取监视器的一部分,本地缓存将失效,以便后续读取将直接进入主内存,而不是本地缓存强>
那么,为什么在代码中我必须声明实例为volatile,因为当第二个线程进入同步块时,它将直接进入主内存
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;
}
}
我的意思是,当另一个线程进入同步块并进行第二次检查时,它应该像前面提到的那样从主内存更新
# 1 楼答案
必须将其声明为volatile,否则无法保证对getInstance()的两个调用将返回同一个实例
不能保证主内存会被访问,只有缓存一致的值。i、 e.所有螺纹将看到相同的值
顺便说一句:你当然知道它比需要的复杂得多。你所需要的只是
做了几乎相同的事情
# 2 楼答案
比赛条件如下:
线程A看到
instance == NULL
,正在运行此代码instance = new MySingleton();
。对instance
的写入可见,但对MySingleton
的写入尚未可见线程B看到
instance != NULL
并开始处理实例线程B现在正在处理一个它看不到其结构的对象
使
instance
易失性解决了这个问题,因为JDK内存规范(从JDK5开始)保证了对非易失性对象的写入不会与对易失性对象的写入顺序不一致。因此,任何看到instance != NULL
的线程都必须看到实例本身