new*_*man 8 java memory-model jls
当且仅当所有顺序一致的执行没有数据争用时,程序才能正确同步.
根据讨论,如果一个正确同步的程序仍允许数据竞争吗?(第一部分),我们得出以下结论:
程序可以正确同步并具有数据竞争.
两个结论的结合意味着它必须存在这样一个例子:
程序的所有顺序一致的执行都是数据竞争的,但是这样的程序的正常执行(除了顺序一致的执行之外的执行)包含数据竞争.
经过深思熟虑,我还是找不到这样的代码样本.那你呢?
"程序可以正确同步并进行数据竞争"是不正确的.该讨论中assylias的示例未正确同步.从更高级别的功能角度看它是正确的 - 它包含的数据竞争并不表现为错误.这是一种所谓的"良性"数据竞争,但在讨论JLS定义时这是无关紧要的.
保证顺序一致执行不包含数据争用的程序在任何执行中都不包含数据争用,顺序一致或不一致.正如JLS所说,
这对程序员来说是一个非常强大的保证.程序员不需要推理重新排序以确定他们的代码包含数据竞争.因此,在确定其代码是否正确同步时,他们不需要推理重新排序.一旦确定代码被正确同步,程序员就不必担心重新排序会影响他或她的代码.
所以请注意,正确同步的程序的定义被缩小到只有顺序一致的执行,这是对程序员的礼貌,这使他有力地保证顺序一致的执行是他或她需要推理的唯一执行和所有其他执行将自动拥有相同的保证.
在JMM使用的术语中很容易迷失方向,微妙的误解会导致后来的误解.因此,请记住这些:
这是一个违反直觉的定义,所以我们必须要小心:每次我们说执行时,我们必须确保想象一袋行动,而不是一串行动.每当我们定义一个部分订单时,我们应该想象几个袋子排成一列.
有趣的是,如果所有共享变量都是易失性的,那么同步顺序将变为总顺序,因此将满足执行顺序的定义.这样,我们从一个不同的角度得出结论,即这样一个程序的所有执行都是顺序一致的.
我深入研究了数据竞争定义中JLS漏洞的底部:
"当一个程序包含两个冲突访问(第17.4.1节)时,这些访问不是由先发生过的关系排序的,而是说它包含数据竞争."
首先,它不是程序包含数据的种族,而是一个程序执行.如果我们回顾一下定义Java内存模型的原始论文,我们会看到这个更正:
"两个访问x和y在执行程序时会形成一个数据竞争,如果它们来自不同的线程,它们会发生冲突,并且它们不是按先发生的顺序排序的."
但是,这仍然使我们对易失性变量的行为被定义为数据竞争.考虑以下事件 - 在图之前:
Thread W w1 ----> w2
|
\
Thread R r0 ----> r1
Run Code Online (Sandbox Code Playgroud)
r1观察写w1.之前是另一个读取r0,写入之后是另一个读取,w2.现在注意到r0与w1或w2之间没有路径; 同样在r1和w2之间.所有这些都是定义中数据竞争的例子.
然而,深入挖掘,我在memoryModel邮件列表上找到了这篇文章.它说"数据竞争应被定义为非易失性变量的冲突行为,这些变量不是按先发生顺序排序的".只有这样的补充才会关闭漏洞,但这仍然没有进入正式的JLS版本.