我想澄清一下,在关系对易失性变量起作用之前是如何发生的。让我们有以下变量:
public static int i, iDst, vDst;
public static volatile int v;和线A:
i = 1;
v = 2;以及线程B:
vDst = v;
iDst = i;下列语句是否符合Java模型(JMM)?如果不正确,什么是正确的解释?
i = 1总是发生在v = 2之前v = 2发生在JMM中的vDst = v之前,但前提是它确实发生在时间之前i = 1发生-在JMM中的iDst = i之前( iDst将被可预测地分配给1),如果v = 2在v = 2时间之前实际发生i = 1和iDst = i之间的顺序是未定义的,iDst的结果值也未定义。逻辑中的错误:
在JMM中没有“挂钟时间”的概念,我们应该依赖同步顺序作为v = 2和vDst = v的排序指南。有关更多细节,请参见所选答案。
发布于 2015-05-14 20:43:49
i = 1总是发生在v = 2之前是真的。由JLS部分17.4.5,
如果x和y是同一个线程的动作,x以程序顺序出现在y之前,则hb(x,y)。
v = 2发生在JMM中的vDst = v之前,但前提是它确实发生在时间之前i = 1发生-在JMM中的iDst = i之前( iDst将被可预测地分配给1),如果v = 2在v = 2时间之前实际发生假。在秩序之前发生的事情并不能保证在物质时间发生在彼此之前的事情。来自司法系统的同一部分,
应当指出的是,在两项行动之间的关系发生之前就出现了一种情况,并不一定意味着它们必须在执行中按这种顺序进行。如果重新排序会产生与合法执行一致的结果,则不违法。
然而,它保证v = 2发生在vDst = v和i = 1发生之前,如果v = 2以同步顺序出现在vDst = v之前,则执行的同步操作的总顺序通常被误认为是实时顺序。
i = 1和iDst = i之间的顺序是未定义的,iDst的结果值也未定义。如果vDst = v按同步顺序出现在v = 2之前,则是这种情况,但实际时间并没有进入其中。
发布于 2015-05-14 21:10:41
所有同步操作(易失性w/r、锁/解锁等)形成一个整体顺序。这是一个非常有力的声明,它使分析更容易。对于易失性的v,按照这个顺序,读在写之前,或者写在读之前。当然,订单取决于实际执行情况。
从整个秩序,我们可以确定部分订单发生-之前。2如果变量(易失性或非易失性)上的所有读和写都在一个偏序链上,那么很容易分析--读可以看到前面的写。这就是JMM的要点--在读/写上建立命令,这样就可以像顺序执行一样推理它们。
但是,如果易失性读取在易失性写入之前呢?我们在这里需要另一个关键的约束--读不能看到写的内容。3.
因此,我们可以推论,
v可以看到0 (init值)或2(易失性写入)。happens-before链。i的最后一点读取必须看到对i的一种写入;在本例中,0或1。它将永远不会从任何写入中看到神奇的值。
引用java8规范:
1
2
3.
对总顺序的随机思考:
由于这个总顺序,我们可以说一个同步动作发生在另一个同步动作之前,就像在时间上一样。这一时间可能不符合挂钟,但它并不是一个坏的心理模型,我们的理解。(实际上,java中的一个操作对应于大量的硬件活动,不可能为其定义一个时间点)
甚至物理时间也不是绝对的。记住,光在1ns中传输30厘米;在今天的CPU上,时间顺序绝对是相对的。总的顺序实际上要求从一个动作到另一个动作之间存在因果关系。这是一个非常强的需求,您可以打赌JVM会尽力优化它。
https://stackoverflow.com/questions/30246007
复制相似问题