发生在Java内存模型中的关系之前

时间:2014-12-24 12:16:36

标签: java jvm jvm-hotspot java-memory-model happens-before

关于JLS ch17 Threads and Locks,它说“如果一个动作发生在另一个动作之前,则第一个动作在第二个动作之前可见并在第二个之前命令”;我想知道:

(1)说“之前订购”的真正含义是什么?因为即使action_a发生在action_b之前,action_a也可以在action_b之后执行,对吧?

(2)如果action_a发生在action_b之前,是否意味着action_a绝不能看到action_b?或者action_a可能会看到或看不到action_b?

(3)如果action_a没有发生 - 在action_b之前,而action_b没有发生 - 在action_a之前,是否意味着action_a可能会看到或看不到action_b?

(4)以前没有任何循环发生,对吧?

任何答案都将不胜感激:)

2 个答案:

答案 0 :(得分:6)

  

(1)在#34;之前订购"它真正意味着什么?因为即使action_a发生在action_b之前,action_a也可以在action_b之后执行,对吧?

发生前因果,而不是时间关系。 action_aaction_b之前被{{1}}因果关系排序,无论它是否真正在它之前执行。然而,在实践中,运行时很难在没有时间顺序的情况下保持因果关系。查看my earlier question,其中详细介绍了因果关系。

  

(2)如果action_a发生在action_b之前,是否意味着action_a绝不能看到action_b?或者action_a可能会看到或看不到action_b?

对彼此的行动可见性有一个明确的整体顺序。这由指定格式良好的执行的部分处理。因此,对于任何两个操作 a b a b b可见 a ,或者以上都不是。理解精心构造的执行概念的好读物是Java Memory Model Examples: Good, Bad, and Ugly

  

(3)如果action_a没有发生 - 在action_b之前,而action_b没有发生 - 在action_a之前,是否意味着action_a可能会看到或看不到action_b?

是的,两者都有可能。无论如何都无法保证。

  

(4)以前没有任何循环发生,对吧?

Happens-before 必须强加部分排序,而排序的关键属性是无循环。

答案 1 :(得分:2)

  

说“之前订购”是什么意思?因为即使   action_a发生在action_b之前,action_a可以在执行之后执行   某些实现中的action_b,对吧?

在关系之前发生会产生一个内存屏障,阻止在action-a之前执行action-b。因此某些基础JVM优化无法应用。因此,操作-a 无法在action-b之后或之后执行。

  

如果action_a发生在action_b之前,是否意味着action_a绝不是   看action_b?或者action_a可能会看到或看不到action_b?

这意味着action-b 必须看到行动带来的所有更改

  

如果action_a没有发生 - 在action_b之前,而action_b没有发生   发生在action_a之前,是否意味着action_a可能看到或未看到   action_b?

发生前传递关系。因此,如果action-a发生在action-b之前,它发生在action-c之前......那么就是action-y,而action-y发生在action-z之前,那么action-a发生在action-z之前。

在关系确保操作跟随当前操作之前发生的事件将看到当前操作所做的更改。如果未看到更改,则不存在之前发生。

  

以前没有任何循环发生,对吧?

是的,如果action-a发生在action-b,action-c,action-d之前,则b,c,d中的任何一个都不会发生在action-a之前。

修改:

JLS说应该注意的是,两个动作之间存在的先发生关系并不一定意味着它们必须在实现中以该顺序发生。如果重新排序产生的结果与合法执行一致,则不是非法的。。因此,如果action-a在与action-b的关系之前发生了,则action-b可以先执行,前提是如果action b在action b之前执行,则final会等同于sate。这是特定于实现的。如果按顺序更改不影响最终结果,则JIT可能决定比操作更早地运行action-b。

  1. 好吧,action-a是独立的 action-b。至少在理论上:)

  2. 指定顺序操作之前发生。如果操作是 parallel ,则之前发生的操作不存在。

  3. 注意:所有这些混淆是因为如果两个操作之间没有依赖关系,那么删除会在之前由JIT发生。请阅读Escape analysis