理解线程内语义

时间:2014-09-07 14:06:37

标签: java multithreading java-memory-model

你能用简单的词语解释什么"程序满足线程内语义"手段?是否有可能提供满足这些语义的程序的简单例子?

2 个答案:

答案 0 :(得分:8)

内部线程语义的概念在JLS section 17.4中讨论,其中涵盖了Java内存模型。 JMM是JVM执行Java程序的一组要求和约束。这是17.4中相关的文字部分:

  

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

这意味着,就单个线程而言,对象中可见的值是'字段是字段'初始值(零,假或空)或者是此线程先前写过的值。

这很明显是基本的;为什么要说明呢?

考虑一个带有几个int字段的单线程Java程序:

field1 = 1;                // 1
field2 = 2;                // 2
field3 = field1 + field2;  // 3

然后显然field3的值必须为3.这是因为第3行field1field2中可见的值必须反映早期值如果在第3行的计算中使用field1field2的初始值为零,那么这将是错误的,因为这些字段的分配在程序中比计算。

不太明显的是存在的约束。例如,此处对field1field2写入的排序没有约束。 JVM可以在第1行之前执行第2行,并且程序的结果将是相同的。或者,它可以将写入延迟到field1field2并将这些值保存在寄存器中,并在第3行进行基于寄存器的添加。所有字段的实际写入可能会延迟到很晚。或者,如果随后该线程覆盖了这些值,它们甚至可以完全省略。同样,该计划的结果将是相同的。

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

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

答案 1 :(得分:1)

我们将其分解为:https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4

1 内存模型决定了程序中每个点可以读取的值。 2 每个单独的线程的行为必须遵循该线程 3 的语义所控制。每次读取看到的值由内存模型确定。 4 提及此内容时,我们说该程序遵循线程内语义。线程内语义是单线程程序的语义,它允许基于线程内的读取操作看到的值来完全预测线程的行为

1。 The memory model determines what values can be read at every point in the program

这意味着JMM具有可见性和排序规则,这些规则决定了读取的值-尚未定义的规则但会使读者意识到它们存在(它们在 3 和< strong> 4 与线程内语义之间的关系)

2。 The actions of each thread in isolation must behave as governed by the semantics of that thread

在这种情况下,它没有定义什么是“隔离”,也没有定义什么是“该线程的语义”,但是它们可能意味着动作不属于线程间动作,因此所有由线程完成的动作都不属于线程间动作。影响其他线程将逐行读取(线程的语义)。它们对线程内操作的“定义”(只是给出一个例子)是:

This specification is only concerned with inter-thread actions. We do not need to concern ourselves with intra-thread actions (e.g., adding two local variables and storing the result in a third local variable)”-即不会影响任何共享内存的任何操作。

3。 with the exception that the values seen by each read are determined by the memory model.

这意味着即使某个线程执行对其他任何线程都没有影响的代码( 2 ),JMM也会应用其规则-它规定了这些读取的值。

4。 When we refer to this, we say that the program obeys intra-thread semantics. Intra-thread semantics are the semantics for single-threaded programs, and allow the complete prediction of the behavior of a thread based on the values seen by read actions within the thread

总而言之,他们说-如果您有一个线程单独执行某项操作,则意味着不在任何共享内存中操纵(读取或写入)数据。该代码中的读取值仍将由* JMM决定,并且所有(全部)信息将被同一线程知道-这就是遵循线程内语义的意思


在这里他们几乎隐式地描述了顺序一致性(SC),而没有实际说出来,唯一缺少的部分是线程间操作-稍后将在程序顺序(*由JMM决定)中使用它,这需要所有定义此处定义何时使用SC。

程序顺序是他们一直不提及而提到的规则,它表示如果您查看线程中的所有(全部)动作(内部和内部)并将其视为线程内语义,则它们都被视为顺序的一致。


  • 通过阅读Stuart Marks answer

    您可以了解什么是SC。
  • 作为旁注,我只需要说JLS for JMM中的措辞太可怕了,如果他们尝试这样做,他们就不会变得更加混乱。