关于单例模式懒汉式的线程安全问题,synchronized,volatile的使用

首先将正确代码放出来

同时说明一下,单例模式的饿汉式是线程安全的,因为一开始就已经将唯一的对象创建好了,调用时只要返回就行了
懒汉式线程安全
以上是一个正确的线程安全的懒汉式写法,这里主要讲两个知识点,一个是synchronized代码块的作用,一个是volatile的作用。

java内存模型(JMM)

java内存模型

synchronized如何做到可见性

在这里插入图片描述
如果没有加synchronized代码块,那么可能多个线程同时读取到instance为空的情况,这样就会创建多个对象,从而不能保证单例模式,只有synchronized代码块执行完后,instance才会同步到主内存中,并且这期间不能有其他线程进行访问,从而也就保证了线程安全

为什么判断两次instance==null

第一次判断是在代码块前,第二次是进入代码块后,第二个判断想必都知道,多个线程都堵到代码块前等待锁的释放,进入代码块后要获取到最新的instance值,如果为空就进行创建对象,那么为什么还要进行第一个判断,第一个判断起到优化作用,假设如果instance已经不为空了,那么没有第一个判断仍然会有线程堵在代码块前等待进一步判断,所以如果不为空,有了第一个判断就不用再去进入代码块进行判断,也就不用再去等锁了,直接返回。

为什么instance还要加volatile关键字

volatile使用场景
在这里插入图片描述
既然synchronized块已经起到及时将instance更新到主内存中,并保证了线程安全,那么为什么还要加volatile关键字呢,其实也是起到一个优化作用,synchronized块只有执行完才会同步到主内存,那么比如说instance刚创建完成,不为空,但还没有跳出synchronized块,此时又有10000个线程调用方法,那么如果没有volatile,此使instance在主内存中仍然为空,这一万个线程仍然要通过第一次判断,进入代码块前进行等待,正是有了volatile,一旦instance改变,那么便会同步到主内存,即使没有出synchronized块,instance仍然同步到了主内存,通过不了第一个判断也就避免了新加的10000个线程进入去争取锁。

发布了43 篇原创文章 · 获赞 12 · 访问量 4668

猜你喜欢

转载自blog.csdn.net/Jarbein/article/details/102495075