单列模式之volatile

来源:互联网 发布:win7仿mac dock栏 编辑:程序博客网 时间:2024/06/07 02:47

单例模式应该是我们开发人员最早而且是最熟悉的设计模式,
不管是公司项目,还是开源项目或者是jdk源码中都有大量的应用
今天分析下单列模式为什么要加volatile关键字
代码:

public class Singleton {    private static volatile Singleton singleton;    private Singleton() {    }    public static Singleton getInstance() {        if (singleton == null) {            synchronized (Singleton.class) {                if (singleton == null) {                    singleton = new Singleton();                }            }        }        return singleton;    }}

解释几个概念:

  1. 指令重排序:CPU在执行一批指令时,为了连续性和资源利用会对指令进行重排序,Java中会保证单线程执行结果是不能被改变的
  2. 内存屏障:Java为了防止cpu指令的重排序会在指定的指令前后加上内存屏障,是由Java内存模型定义的

单例实现方式:
1.及时加载(类第一次加载到方法区时就会初始化单例对象)
2.延迟加载(单例对象第一次使用的时候才会初始化),上面代码是属于延迟加载实现方式一种,叫双重检查锁实现

分析:
这句代码 singleton = new Singleton();
拆分3个步骤:
1 .分配内存空间
2. new Singleton() 初始化
3. 对象内存引用赋值给singleton
4. singleton 变量的使用
不加volatile的情况下:第2步和第3步可能会被重排序执行序列 1-3-2-4
多线程访问情况:
线程1:执行顺序 1-3-2-4
线程2:如果线程1执行到 3,这个时候线程2会在第一次检查是否为空时候发现对象不为空,返回一个没有正确初始化的对象并使用 ,从而导致系统异常
加上volatile:
volatile 修饰的变量会在写的前后加上内存屏障,禁止指令重排序 ,所以执行顺序就只会是1-2-3-4,
线程2 发现singleton 不为空的时候一定是一个初始化成功的对象,从而保证系统正常

原创粉丝点击