关于多线程同步的一切:乱序执行和内存屏障

所以CPU0收到Read消息后,会把b的0值发给CPU1,所以继续在`while (b);简而言之,Core执行到write memory barrier(wmb)的时候,如果Store Buffer还有悬而未决的store操作,则都会被mark上,直到被标注的Store操作进入内存后,后续的Store操作才能被执行,因此wmb保障了barrier前后操作的顺序,它不关心barrier前的多个操作的内存序,以及barrier后的多个操作的内存序,是否与Global Memory Order一致。...
摘要由CSDN通过智能技术生成

程序序(Program Order)

对单线程程序而言,代码会一行行顺序执行,就像我们编写的程序的顺序那样。比如:

a = 1;
b = 2;

会先执行`a = 1`,再执行`b = 2`,从程序角度看到的代码行依次执行叫程序序,我们在此基础上构建软件,以此作为讨论的基础。

内存序(Memory Order)

与程序序相对应叫内存序,是指从某个角度观察到的对于内存的读和写所真正发生的顺序。

内存操作顺序并不唯一,在一个包含core0和core1的CPU中,core0和core1有着各自的内存操作顺序,这两个内存操作顺序不一定相同。

从包含多个Core的CPU的视角看到的全局内存操作顺序(Global Memory Order)跟单core视角看到的内存操作顺序亦不同,而这种不同,对于有些程序逻辑而言,是不可接受的,例如:

程序序要求`a = 1`在`b = 2`之前执行,但内存操作顺序可能并非如此,对a赋值1并不确保发生在对b赋值2之前。

  • 如果编译器认为对b赋值没有依赖对a赋值,那它完全可以在编译期为了性能调整编译后的汇编指令顺序
  • 即使编译器不做调整,到了执行期,也有可能对b的赋值先于对a赋值执行

虽然对一个Core而言,如上所述,这个Core观察到的内存操作顺序不一定符合程序序,但内存操作序和程序序必定产生相同的结果,无论在单Core上对a、b的赋值哪个先发生,结果上都是a被赋值为1、b被赋值为2,如果单核上,乱序执行会影响结果,那编译器的指令重排和CPU乱序执行便不会发生,硬件会提供这项保证。

但多核系统,硬件不提供这样的保证,多线程程序中,每个线程所工作的Core观察到的不同内存操作序,以及这些顺序与全局内存序的差异,常常导致多线程同步失败,所以,需要有同步机制确保内存序与程序序的一致,内存屏障(Memory Barrier)的引入,就是为了解决这个问题,它让不同的Core之间,以及Core与全局内存序达成一致。

乱序执行(Out-of-order Execution)

乱序执行会引起内存顺序跟程序顺序不同,乱序执行的原因是多方面的,比如编译器指令重排、超标量指令流水线、预测执行、Cache-Miss等。内存操作顺序无法精确匹配程序顺序,这有可能带来混乱,既然有副作用,那为什么还需要乱序执行呢?

答案是为了性能。

我们先看看没有乱序执行之前,早期的有序处理器(In-order Processors)是怎么处理指令的?

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值