在阅读了this question和this (特别是第二个答案)之后,我对易失性及其在内存屏障方面的语义感到非常困惑。
在上面的例子中,我们写入一个易失性变量,这会导致一个mfence,它会依次将所有挂起的存储缓冲区/加载缓冲区刷新到主缓存,从而使其他缓存线无效。
然而,非易失性字段可以被优化并存储在寄存器中,例如?那么,我们如何才能确保写入到易失性变量之前的所有状态更改都是可见的呢?如果我们有1000件东西呢?
发布于 2017-08-11 07:47:43
在上面的例子中,我们写一个易失性变量,这会导致一个mfence,然后它会将所有挂起的存储缓冲区/加载缓冲区刷新到主缓存中...
这是正确的。
正在使其他缓存线无效的
。
这是不正确的,或者至少是误导性的。使其它高速缓存线无效的不是写存储器屏障。它是在其他处理器中运行的读内存屏障,它使每个处理器的高速缓存线无效。内存同步是线程写入和从volatile变量读取的其他线程之间的协同操作。
Java内存模型实际上保证了只有对写入的相同变量的读取才能保证更新该变量。实际情况是,在跨越写存储器屏障时,所有存储器高速缓存线都会被刷新,并且当跨越读存储器屏障时,所有存储器高速缓存线都会失效--而不管正在访问的变量是什么。
然而,非易失性字段可以被优化并存储在寄存器中,例如?那么,我们如何才能确保写入到易失性变量之前的所有状态更改都是可见的呢?如果我们改变1000件事呢?
根据this documentation (和其他人)的说法,内存屏障还会导致编译器生成刷新寄存器的代码。引述如下:
...当使用barrier()时,编译器必须丢弃当前缓存在任何机器寄存器中的所有内存位置的值。
https://stackoverflow.com/questions/45602130
复制相似问题