可见性的保证要穿透jvm,直接从底层做起。对于volatile的写操作,jvm编译的时候,会在前面加上一条以lock为前缀的汇编指令。lock指令会引起以下两个动作:引起总线锁(不一定,要看cacheline的状态,Exclusive和Modified不会)强制刷新storeBuffer,去内存《并发编程的艺术》,volatile具有同步语义,因为第一个动作。确保可见性的主要原因之一是第二个动作。还有一个原因是ESMI协议,变成Invalid状态的cacheline需要重新拉取。每个CPU都有一个storeBuffer。存储的时候,不会马上存入缓存,而是先存入storeBuffer,在可选的时候再存入缓存。每个cup的storeBuffer只对自己可见,其他CPU无从得知(即无法通过总线获取)。这就是隐形的根本原因!造成看不见的根源!造成看不见的根源!因此,在强制刷新后,它将可见。过程是这样的:当一个volatile变量被修改时,store时会存储到storeBuffer中。然后,强制将storeBuffer刷入缓存,再从缓存写入内存。然后当前cpu会向总线发送一个信号,通知其他cpusvolatile变量所在的那行已经改变,需要设置为invalid(EMSI协议)。当其他CPU中的线程要读取这个volatile变量时,它们必须重新拉取数据。首先,遍历总线,在其他cpu缓存中查找。如果不是,则必须将其从内存中拉出。因为在改变volatile变量之前,缓存和内存中的变量已经被更新了。所有的吸引力都是新的价值。
