我正在从原始论文Memory Barriers: a Hardware View for Software Hackers复制该图的文字。
表4显示了三个代码片段,由CPU 0,1和2同时执行。所有变量最初都为零。
请注意,CPU 1和CPU 2都不能进入第5行,直到它们在第3行看到CPU 0分配给“b”。一旦CPU 1和2在第4行执行了内存屏障,它们都可以保证看到CPU 0在第2行的内存屏障之前的所有赋值。类似地,第8行的CPU 0的内存屏障与第4行的CPU 1和2的内存屏障配对,因此CPU 0将不会在第9行执行“e”的赋值直到它分配给“a”后才能看到其他两个CPU。因此,第2行的CPU 2断言保证不会触发。
对我来说,CPU0上的第6-9行似乎根本没用,因为CPU 0的第2行的内存屏障和CPU 1和2的第4行的内存屏障保证了b=1
的效果被选中以及之前的所有商店,又名a=1
。然后,断言e == 0 || a == 1
总是成功。
我不知道我是否忽视了任何事情。任何澄清都表示赞赏。
答案 0 :(得分:1)
将第6-9行从CPU 0中删除肯定会阻止assert()被触发。然后,在e
被初始化为零的情况下,删除断言以外的所有代码也是如此。但是,这两种修改都没有用。相反,断言的关键点是问题" CPU 2是否有可能在执行结束时看到状态e==1&&a==0
?"以这种方式看待它应该迫使你根据什么顺序传播的值来思考。
但是你忽略的主要是这篇论文非常古老,从那时起,在理解和形式化内存排序方面取得了巨大的进步。我正在向Is Parallel Programming Hard, And, If So, What Can You Do About It?添加新的内存订购章节。与此同时,这对LWN文章here和here可能会有所帮助。
或者,如果您想查看该书的当前状态git clone git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/perfbook.git
。