Java内存模型的三大特性

2018-04-12  本文已影响56人  zivxia

之所以关注这个java内存模型的三大特性,源于看到java单例模式的最佳懒汉模式的写法:

// 双重校验锁DCL(double checked locking)
public class Singleton {
    private static volatile Singleton sInstance;
    private Singleton() {
    }
    public static Singleton getInstance() {
        if (sInstance == null) {
            synchronized (Singleton.class) {
                if (sInstance == null) {
                    sInstance = new Singleton();
                }
            }
        }
        return sInstance;
    }
}

如果没有用volatile修饰的话,这个获取到的单例实例是有问题的。因为

sInstance = new Singleton();

不是原子性的,它其实是一下三个步骤

这三个步骤不一定是按顺序执行的,因为在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。所以可能执行的顺序是1-->3-->2
当执行完3时,这时候sInstance不为空,但是未进行初始化,这时候cpu切换执行权,另外一个线程在执行外层的

if(sInstance == null){
}

发现sInstance不为null,则直接return回来了,因为这个实例是未进行初始化的,所以是有问题的。
这是后就必须加上volatile,volatile能保证可见性和有序性,可以阻止

sInstance = new Singleton();

的重排序,按照正常1-->2-->3执行。而synchronized只能保证互斥性和原子性。这里可以参考下,大神的关于java内存模型的知识

Java并发编程:volatile关键字解析

上一篇 下一篇

猜你喜欢

热点阅读