在Java中,当有两个线程共享以下变量时:
int a;
volatile int b;如果线程1做到了:
a = 5;
b = 6;然后在这两个指令之间插入一个StoreStore屏障,'a‘被冲回主内存。
现在,如果线程2做到了:
if(b == 6)
a++;在之间插入一个LoadLoad屏障,并且我们保证,如果新值'b‘是可见的,那么'a’的新值也是可见的。但这实际上是如何实现的呢?LoadLoad是否使CPU缓存/寄存器失效?或者只是指示CPU从CPU中再读取变量的值?
我发现了有关LoadLoad屏障(http://gee.cs.oswego.edu/dl/jmm/cookbook.html)的信息:
LoadLoad屏蔽了顺序: Load1;LoadLoad;Load2,确保在Load2访问数据和加载所有后续加载指令之前加载load 1的数据。通常,在执行推测负载和/或无序处理的处理器上需要显式的LoadLoad屏障,在这些处理中等待负载指令可以绕过等待存储。在保证始终保持负载排序的处理器上,这些障碍相当于无操作。
但这并不能真正解释这是如何实现的。
发布于 2013-03-12 12:46:39
我将举一个例子说明如何实现这一目标。您可以阅读更多关于细节这里的内容。对于x86处理器,正如您所指出的那样,LoadLoad最终是不操作的。在我链接的文章中,Mark指出
道格列出了StoreStore,LoadLoad和LoadStore
因此,从本质上讲,唯一需要的障碍是用于x86体系结构的一个x86。那么,这是如何在低水平上实现的呢?
以下是博客的摘录:
,这是它为易失性和非易失性读取生成的代码:
nop ;*synchronization entry
mov 0x10(%rsi),%rax ;*getfield x和用于易失性写入:
xchg %ax,%ax
movq $0xab,0x10(%rbx)
lock addl $0x0,(%rsp) ;*putfield xlock指令是道格食谱中列出的StoreLoad。但是,锁指令还将所有读取与其他进程同步,如挂牌。
锁定指令可用于同步由一个处理器编写的数据和由另一个处理器读取的数据。
这减少了为易失性负载发出LoadLoad LoadStore屏障的开销。
话虽如此,我还是要重申亚述人所指出的。发生这种情况对开发人员来说并不重要(如果您对处理器/编译器实现者感兴趣,那就另当别论了)。volatile关键字是一种接口,表示
发布于 2013-03-12 15:40:44
如果该LoadLoad计算结果为no-op,那么线程2可以继续使用缓存的值。
这包括在烹饪书中的“可以点菜”表中。
编程顺序是
read b
read a
write a所谓“缓存a",意思是代码被重新排序。
read a
...
read b这种重新排序是被禁止的。
https://stackoverflow.com/questions/15360598
复制相似问题