并发编程之可见性

可见性

每个线程都会有一个线程的副本(也叫缓存),这个缓存是指CPU中L1、L2、L3三级高速缓存,第一次会去主存中拿到值并且copy到每个线程的副本中,而后每个线程再去更改值或状态时,只会更改当前线程副本的值或状态,不会重新去主存读取最新的值或状态,那么就会导致一个线程更改了值或状态,另外一个线程无法得到最新的值或状态,就会使线程间不可见,这就是线程的可见性问题。

volatile可以保证线程间的可见性

volatile修饰引用类型时只能保证引用本身的可见性,不能保证内部字段的可见性

volatile修饰了a引用,并由a指向堆中的A,A中有running值为true,但是由于volatile没有修饰running,只是修饰了a引用,所以A中的running对于线程之间是不可见的,只是引用a可见,所以该程序一直会死循环,main线程更改了running的值,但是另外一个线程收不到最新更改的值,使用volatile修饰running使程序才能正确执行。

三级缓存

寄存器需要数据x,首先去L1找,如果L1没有,则会去L2找,L2没有就会去L3找,L3没有才会去主存找。往回存数据时,也是先在L3存一份,然后L2存一份,L1存一份,然后读到寄存器里面。线程之间的可见性重点指的多核CPU L1之间的数据的可见性。

缓存行概念 cache Line

按块读取,使用程序局部性原理,提高效率

缓存行一行大小为64字节

读取数据时会把当前数据的那一行一次性的缓存到线程本地中来,也就是会把x和y的值一次性缓存到L1与L2中来,但是左边cpu只访问x,由于缓存行的概念,会把与x位于同一行的y也会缓存进来,右边cpu也是同样的概念,只访问y,由于缓存行的概念,会把与y位于同一行的x也会缓存进来。

多颗cpu之间L1缓存之间数据的一致性,这种概念就称为缓存一致性协议,cpu中任意缓存行中修改其中一方的值时,另外的cpu就会去主存重新刷新并且拉取值,多个缓存行之间就会互相干扰

缓存一致性协议与volatile没有关系

MESI 缓存一致性协议 比较有名 MESI是因特尔设计的,还有其他的缓存一致性协议

M:Modified 被修改了

E:Exclusive 独享的

S:Shared 共享

I:Invalid 失效

为什么缓存行是64字节?

缓存行越大,局部性空间效率越高,但读取时间慢

缓存行越小,局部性空间效率越低,读取时间快,但命中率低,所以取折中64字节

小结

volatile保障线程可见性?

线程本地的缓存互相之间保证数据一致性采用的一种机制,和主存当中的某些数据保持一个同步。此处所指的缓存是CPU中L1、L2、L3三级高速缓存

缓存行?

读取时是按照一行一行来读,程序局部性原理,缓存行的大小为64字节

缓存一致性协议?

CPU之间L1、L2、L3缓存之间数据的一致性,这种概念就称为缓存一致性协议,CPU中任意缓存行中修改其中一方的值时,另外的CPU就会去主存重新刷新并且拉取值,多个缓存行之间就会互相干扰

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

连梓豪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值