Java内存模型的顺序一致性与Leslie Lamport定义有何不同?

3

JLS-17.4.3定义了每个线程的程序顺序,其中线程内程序的任何重新排序都将保留线程内语义。然后它根据程序顺序定义了顺序一致性。它说,顺序一致性是与程序顺序一致的所有操作的总顺序。

现在我有一个问题,程序顺序是针对每个线程定义的,而顺序一致性是跨所有线程定义的。这是否违反了Leslie Lapmort定义的顺序一致性?-

任何执行的结果都与如果所有处理器的操作按某个顺序执行相同,并且每个单独处理器的操作在此序列中按其程序指定的顺序出现。

例如,如果编译器查看特定线程的代码(线程的程序顺序),重新排序存储和加载会怎样?


编辑:以下部分涉及来自youtube的此会话。

Java内存模型实用性 - 第48分钟

第一个示例显示了两个线程的两次执行。每个执行的顺序保留了线程内语义。下一个示例显示了相同的执行集,但是左侧执行已经重新排序了Thread-1的操作。

现在,如果我们只考虑Thread-1的程序顺序,那么重新排序是合法的。但是演讲者所说的是它违反了顺序一致性。但是当我阅读JLS时,我得到的印象是重新排序的执行是有效的,并且由于具有两个合法的程序顺序而保持顺序一致性。我的理解是否错误?如果是,请解释其中的问题。

int a=0, int b=0;

Thread - 1     Thread - 2 
----------     -----------

r1 = a;         b=2;
r2 = b;         a=1;

After reordering

int a=0, int b=0;

Thread - 1     Thread - 2
----------     ----------
r2 = b;          
                    b=2;
                    a=1; 

r1 = a;        
1个回答

3
我认为这些定义并不矛盾,只是表述方式不同。但对于Java内存模型来说,由于JLS 7.4.3结尾处的以下警告,这一点变得无关紧要:
“如果我们使用顺序一致性作为我们的内存模型,我们所讨论的许多编译器和处理器优化将是非法的。例如,在表17.3的跟踪中,只要将3写入p.x,随后对该位置的读取就需要看到该值。”
换句话说,JMM不以顺序一致性作为其基础。
关于视频中的例子,他的意思如下(我的评论用斜体表示):
- 顺序一致性对程序员来说更容易理解。 (他的观点,但可能是真的。) - 该示例违反了顺序一致性。 (没错,但JMM也没有保证顺序一致性。实际上,JLS本身就有一个“令人惊讶的结果”的例子,归因于JMM不保证顺序一致性!) - 有人应该为JMM提交一个JEP以实现顺序一致性。 (是否应该还有争议,但他们肯定可以这样做。) - 实际分析潜在的优化是否违反顺序一致性很难。 (这也许是JMM不保证顺序一致性的一个很好的理由。如果与现有JMM相比,使用顺序一致性的优化更少,那么在某些情况下,顺序一致性可能会使JIT编译的代码变慢。) 据我所知,从技术角度来看,他没有说什么有争议的话。

注意事项 - 我可能对一致性问题有所错误。但如果您认为我错了,请撰写自己的答案来具体解释不一致性的本质。 - Stephen C
Stephen,能请你观看这个视频中的特定部分并征求您的意见吗?作者谈到了违反顺序一致性的问题。我也会在问题中更新它。 https://youtu.be/TxqsKzxyySo?list=PL2DAEF8634BDD9CF7&t=2883 - psaw.mora
Stephen,这个例子为什么违反了SC?JLS说:“如果所有操作都按照与程序顺序一致的总顺序(执行顺序)发生,则一组操作是顺序一致的”。但程序顺序是针对每个线程定义的,不是吗?那么重排序一个执行怎么会违反SC呢?我的意思是,如果我们只考虑Thread-1的执行,重新排序它是合法的,不是吗?或者JLS真正意味着代码中的操作顺序作为程序顺序吗? - psaw.mora
@psaw.mora 或者按程序顺序,JLS是否真的意味着代码中的操作顺序?是的。JLS说:如果所有操作都按照与程序顺序一致的总顺序(执行顺序)发生,则一组操作是顺序一致的...但请注意,打破顺序一致性对于JVM来说是绝对正常的,因为从未说过它以这种方式运行。 - Eugene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接