注意:我发现这里对读和写的定义太模糊,是否指定某个变量?我觉得是的,要先判断根据关注对象的load/store。
不需要那么复杂得想最理想的状况,只需要把所有情况列出来,然后根据规则排除就行了
CPU 0 CPU 1
A= 1;(a) Y = B(c)
<write barrier> <read barrier>
B = 2(b) X = A(d)
所谓write barrier就是后面的store不会跑到前面的store去,read barrier就是后面的load不会跑到前面的load去。这里从A,B的视角看,b不会跑到a前面去,d不会跑到c前面去。
对A、B的写和对A、B的读满足:这里刚好a、b都是写,c、d都是读 a->b, c->d
排序情况:
a->b->c->d: ok
a->b->d->c: wrong
a->c->b->d: ok
a->c->d->b: ok
a->d->b->c: wrong
a->d->c->b: wrong
b->a->c->d: wrong
b系列全错
c->a->b->d: ok
c->a->d->b: ok
c->b->a->d: wrong
c->b->d->a: wrong
c->d->a->b: ok
c->d->b->a: wrong
d系列全错
可以看一下合乎规则的顺序
a->b->c->d: ok, Y=2,X=1
a->c->b->d: ok, Y=?,X=1
a->c->d->b: ok, Y=?,X=1
c->a->b->d: ok, Y=?,c开头系列的全错。
c->a->d->b: ok
c->d->a->b: ok
那快速reason,c期望在b之后,那么bc,剩下的组合: 由于a一定在b之前,那么abc;d在c之后,就确定abcd
可以看到根据一个期望的同步,就可以一下确定一个整体的顺序。
结论:注意,在这种场景下写入变量的顺序和读取变量的顺序刚好要是相反的。加了这一对读、写内存屏障后,可以保证,在两个CPU都执行完上面的代码后,如果Y的值等于2,那么X的值一定等于1。Y的值等于2,意味着在CPU0上对B赋值2的语句已经执行过了,由于有写内存屏障的存在,也就意味着对A赋值1的语句在之前肯定也被执行过了。在CPU1上,由于有读内存屏障的存在,表示读取变量A值的语句一定在读取变量B值的语句之后被执行,也就可以保证,这时候变量A的值一定已经被赋值成了1。