JAVA多线程的初级认识2-线程安全性

7 篇文章 0 订阅

线程安全性是一个麻烦的难题~从而造成了多线程代码的难写的重要原因。那就从物理和JMM两个层面去了解安全性是如何出现问题的。

  • 物理层面

由于计算机设备的计算能力不均,大致可分为,IO设备 < 内存  < CPU,由于计算能力相差太大。导致很多的地方需要用到缓存,大致的缓存模型如下:

一级缓存L1:包含数据缓存和指令缓存

二级缓存L2:   各个CPU私有

三级缓存L3:    各个CPU共有

有了缓存,就需要保持缓存和缓存之间,缓存和元数据之间保持一致,从图上来看要么使用总线锁(消耗过大),要么使用缓存所,而缓存锁的实现就是通过缓存一致性协议。最常见的就是MESI(Modified, Exclusive, Shared, Invalid)。简单介绍下:

  1. M(Modify) 表示共享数据只缓存在当前 CPU 缓存中, 并且是被修改状态,也就是缓存的数据和主内存中的数 据不一致

  2. E(Exclusive) 表示缓存的独占状态,数据只缓存在当前 CPU 缓存中,并且没有被修改

  3. S(Shared) 表示数据可能被多个 CPU 缓存,并且各个缓 存中的数据和主内存数据一致

  4. I(Invalid) 表示缓存已经失效

在 MESI 协议中,每个缓存的缓存控制器不仅知道自己的 读写操作,也要监听其他缓存的操作。然后通过协议去更改自己缓存中数据的状态从而保证一致性。但是这样就带来了新的弊端,由于CPU速度最快,如果需要同步等待其他缓存控制器更新完了缓存ACK之后才能够进行下面操作指令的话,又会浪费CPU资源。所以,有引入了StoreBuffer机制。

StoreBuffer的生成是采用了异步的方式,即CPU处理完工作更新缓存之后就进行后面的工作,不管你缓存控制器是否完成相应的更新,缓存控制器只是发送缓存更新的消息,至于其他的缓存控制器的ACK完全是异步的。但是这样就又引入了一个问题,就是异步数据的不可控问题。不知道指令A和指令B谁先谁后完成,从而造成数据的不可控。

  • JMM

java memory model内存模型如下:

各个线程的工作内存更新而不及时刷新到主内存,而另外一个工作内存不能及时通过主内存的到最新的值而进行操作,最后刷新到主内存中,造成了数据的覆盖~从而造成了线程安全问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值