深入并发编程——缓存伪共享问题

深入并发编程——缓存伪共享问题

CPU 缓存结构

在这里插入图片描述
一个 CPU 里通常会有多个 CPU 核心,比如上图中的 1号和 2 号 CPU 核心,并且每个 CPU 核心都有自己的 L1 Cache 和 L2 Cache,而L1 Cache 通常分为 dCache(数据缓存)和 iCache(指令缓存),L3Cache 则是多个核心共享的,这就是 CPU 典型的缓存层次。

缓存访问速度

在这里插入图片描述
可以看到缓存离 cpu 越远读取速度越慢。为了提高速度,先把数据读到缓存中能很好提升性能。

缓存行

CPU 从内存中读取数据到 Cache 的时候,并不是一个字节一个字节读取,而是一块一块的方式来读取数据的,这一块一块的数据被称为 CPU Line(缓存行),所以 CPU Line 是 CPU 从内存读取数据到 Cache 的单位。缓存行大小一般是 64byte(8 个 long)。

伪共享过程

(1)开始时遍历A和B 都还不在 Cache 里面,假设 1 号核心绑定了线程 A,2号核心绑定了线程 B,线程 A 只会读写变量 A,线程 B 只会读写变量 B。
在这里插入图片描述
(2) 1 号核心读取变量 A,由于 CPU 从内存读取数据到 Cache 的单位是
Cache Line,也正好变量 A 和 B 的数据归属于同一个 Cache Line,所以 A 和 B的数据都会被加载到 Cache 中,并将此 Cache Line 标记为【独占】状态。
在这里插入图片描述
(3)接着,2 号核心开始从内存里读取变量 B,同样也是读取 Cache Line 大小的数据到 Cache 中,此 Cache Line 中的数据也包含了变量 A 和变量 B,此时 1号和 2 号核心的 Cache Line 状态变为【共享】状态。
在这里插入图片描述
(4) 1 号核心需要修改变量 A,发现此 Cache Line 的状态是【共享】,所以先通过总线发消息给 2 号核心,通知 2 号核心把 Cache 中对应的 Cache Line 标记为【已失效】状态,然后 1 号核心对应的 Cache Line 状态变为【已修改】状态,并且修改变量 A。
在这里插入图片描述
(5)之后,2 号核心需要修改变量 B 的值,此时 2 号核心 Cache 中对应的Cache Line 是【已失效】状态,另外由于 1 号核心的 Cache 也有此相同的数据,且状态为【已修改】,所以要先把 1 号核心的 Cache 对应的 Cache Line 写回到内存中,然后 2 号核心再从内存中读取 Cache Line 大小的数据到 Cache 中,最后把变量修改到 2 号核心的 Cache 中,并将状态修改为【已修改】状态。
所以如果 1 号和 2 号 CPU 核心这样持续交替地分别修改变量 A 和变量 B,就会重复上述第四步第五步,Cache 并没有起到缓存的效果,虽然 A 和 B 之间没有任何关系,但是因为同属于一个 Cache Line,这个 Cache Line 中的任意数据被修改后都会互相影响,这种现象就叫伪共享。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值