关于单例模式懒汉式的线程安全问题,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个线程进入去争取锁。
另一方面也是为了防止指令重排序,从new对象在底层分分配内存,初始化对象,引用指向地址三步的话,如果第二步和第三步颠倒了,那么我们拿到引用地址去用的话可能对象还没初始化完全,就会出现问题

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jarbein

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值