我遇到了以下声明:“读取或写入易失性变量会造成内存障碍,在其中整个缓存被刷新/失效。”
现在考虑以下执行场景:
初始volatile boolean barrier;
初始int b = 0;
线程1 b = 1; // write1
线程1 barrier = true; // write2
线程2 barrier = true; // write3
线程2 print(b); // r1
问:线程2是否保证打印1?
基于这种说法,我会回答是:线程1在write2上刷新它的缓存(这样b = 1就会在主内存中结束),而线程2会使它在write3上的缓存无效(这样它就可以从主内存中读取b )。
但是,在相关的JLS部分中,我无法找到这种行为的保证,因为write3是写的,而不是读的。因此,下列看似重要的条款不适用:
写入易失性变量v (§8.3.1.4)同步-与所有后续通过任何线程读取v的(其中“后继”是根据同步顺序定义的)。
我是否遗漏了一些其他的信息,或者我是不是误解了什么?
(有关问题:
发布于 2015-01-14 00:22:06
我认为,您在引用的短语中突出了一个错误的单词(我的意思是,它与读取同步这一事实远不是这里的主要问题):“对易失变量v (§8.3.1.4)的写入同步--与所有后续的线程读取of v同步”。注意,它根本没有提到其他变量的读取。线程-1版本的b可能仍然存在于您所知道的寄存器中。
发布于 2015-01-19 10:05:12
从缓存刷新/失效的角度来说,易失性的推理会导致更多的混乱,而且不会呈现全貌。
对易失性变量v (§8.3.1.4)的写入与任何线程对v的所有后续读取同步(其中“后继”是根据同步顺序定义的)。
变量的易失性写入,然后在其他线程中读取该变量,在被拒者之前建立了较弱的一致性。
,即在op代码中稍加修改
thread 1 b = 1; // write1
thread 1 barrier = true; // write2
thread 2 while(!barrier) // read barrier
thread 2 print(b); // r1现在,它保证打印b为1。
现在,如果您看到线程2将屏障读为真,那么线程2将确保看到在按程序顺序写入屏障之前所发生的一切。
如果您需要在屏障方面看到易失性,请参考http://gee.cs.oswego.edu/dl/jmm/cookbook.html。
简而言之,易失性实现调用两种情况,第一种编译器在可以优化w.r.t的内容中被限制为易失性读和写。第二,更重要的是,它被实施了。
as volatile read -> loadload
volatile wtire - > storeStore|loadStore
before write and StoreLoad after write.在这里,loadload意味着在读取下一个值之前先处理失效队列,确保读取lates值。StoreStore意味着在写入下一个值之前刷新存储缓冲区。
http://gee.cs.oswego.edu/dl/jmm/cookbook.html。http://www.puppetmastertrading.com/images/hwViewForSwHackers.pdf
https://stackoverflow.com/questions/27933696
复制相似问题