懒汉式比较常见的写法是:
public class Lazy {
private static volatile Lazy instance;
private Lazy(){}
public static Lazy getInstance() {
if (instance == null) {
synchronized (Lazy.class) {
if (instance == null) {
instance = new Lazy();
}
}
}
return instance;
}
}
针对此处volatile
的作用,大部分文章里提到的都是禁止指令重排序
。
但因为最近看了JMM
,产生了一个疑问。
如果不加volatile
,在多线程下同时调用getInstance()
方法,那针对instance
变量,是不是每个子线程都会先从主内存中读取到本地内存中,然后其中一个线程执行了instance = new Lazy();
。此时即便指令重排序了,那也应该是全部执行完,才会从本地内存写会主内存吧。
如果考虑JMM
中的本地内存和主内存的话,真的还需要加volatile
吗?
没有 volatile ,在线程读到 instance 不为 null 的时候,跟其它线程没有“同步”。这时,它虽然可以看到 instance 不是 null ,但是它“看到的” instance 可能并没有初始化结束。
volatile 提供“同步”语义。如果在一个线程里看到是先初始化结束,instance 再被赋值,那么再所有其它线程里看到的也是这个顺序。
不同线程“看到的”指令执行顺序可能是不一样,跟本地内存没有关系。
https://segmentfault.com/q/10...
虽然不是同一种语言,但是如果没有 volatile ,问题和这个一摸一样