设计模式【1.3】-- 为什么饿汉式单例是线程安全的?
我们都知道,饿汉式单例是线程安全的,也就是不会初始化的时候创建出两个对象来,但是为什么呢?
首先定义一个饿汉式单例如下:
之所以是线程安全的,是因为JVM在类加载的过程,保证了不会初始化多个static
对象。类的生命周期主要是:
加载-->验证-->准备-->解析-->初始化-->使用-->卸载
上面的代码,实际上类成员变量instance
是在初始化阶段的时候完成初始化,所有的类变量以及static
静态代码块,都是在一个叫clinit()
的方法里面完成初始化。这一点,使用jclasslib
可以看出来:
clinit()
方法是由虚拟机收集的,包含了static
变量的**赋值操作**以及static
代码块,所以我们代码中的static Singleton instance = new Singleton();
就是在其中。虚拟机本身会保证clinit()
代码在多线程并发的时候,只会有一个线程可以访问到,其他的线程都需要等待,并且等到执行的线程结束后才可以接着执行,但是它们不会再进入clinit()
方法,所以是线程安全的。我们可以验证一下:
首先改造一下单例:
测试代码:
运行结果,一开始运行的时候,我们可以看到线程1进去了static
代码块,它在初始化,线程2则在等待。
待到线程1初始化完成的时候,线程2也不会再进入static
代码块,而是和线程1取得同一个对象,由此可见,static
代码块实际上就是线程安全的。
版权声明: 本文为 InfoQ 作者【秦怀杂货店】的原创文章。
原文链接:【http://xie.infoq.cn/article/c794e14b79159d170f1e26114】。文章转载请联系作者。
评论