理解线程内语义

St.*_*rio 1 java multithreading java-memory-model

你能用简单的词语解释"程序是否满足线程内语义"意味着什么?是否有可能提供满足这些语义并且不满足这些语义的程序的简单示例?

Stu*_*rks 8

JLS第17.4节讨论了线程内语义的概念,它涵盖了Java内存模型.JMM是JVM执行Java程序的一组要求和约束.以下是17.4中相关的文字部分:

内存模型确定可以在程序中的每个点读取哪些值.隔离中每个线程的操作必须遵循该线程的语义,除了每次读取所看到的值由内存模型确定.当我们参考这个时,我们说该程序遵循线程内语义.线程内语义是单线程程序的语义,允许基于线程内读取操作所看到的值完全预测线程的行为.为了确定执行中的线程t的动作是否合法,我们只是评估线程t的实现,因为它将在单线程上下文中执行,如本规范其余部分所定义.

这意味着,就单个线程而言,对象字段中可见的值是字段的初始值(零,false或null),或者是此线程先前写入的值.

这是显而易见的,是基本的; 为什么还要说明呢?

考虑一个包含几个int字段的单线程Java程序:

field1 = 1;                // 1
field2 = 2;                // 2
field3 = field1 + field2;  // 3
Run Code Online (Sandbox Code Playgroud)

然后很明显,值field3必须为3.这是因为在第3行field1field2第3行可见的值必须反映在第1行和第2行写入的较早值.如果在计算中使用的初始值为0 field1或者为零,那将是不正确field2的.第3行,因为这些字段的分配在程序中比计算更早出现.

不太明显的是存在的约束.例如,这里没有关于和的写入顺序的约束.JVM可以在第1行之前执行第2行,并且程序的结果将是相同的.或者,也可能延缓写入和,并保持这些值在寄存器中,做在第3行基于寄存器的除了各个领域的实际写入可能被推迟到更晚.或者,如果随后该线程覆盖了这些值,它们甚至可以完全省略.同样,该计划的结果将是相同的.field1field2field1field2

这就是重点:JVM可以自由地重新安排程序的执行(主要是为了让它运行得更快),但只要它运行单线程就不会改变该程序的结果.这些约束称为线程内语义.允许任何不违反线程内语义的重新排列.

(请注意,上面引用的段落讨论了"遵循线程内语义的程序",但它的真正含义是程序的执行遵循线程内语义.后面的部分中的文本,如17.4.7,更精确,指的是程序的执行是服从内部线程的一致性还是执行的组动作是否符合线程内语义.)