6

关于 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) 不可能有任何循环的happens-before,对吧?

任何答案将不胜感激:)

4

2 回答 2

6

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

Happens-before因果关系,而不是时间关系。action_a因果排序 before action_b,无论它是否实际在它之前执行。然而,在实践中,如果没有时间顺序,运行时将很难维护因果关系。查看我之前的问题,该问题详细介绍了因果关系。

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

动作对彼此的可见性有一个明确的总体顺序。这由指定格式良好的执行部分处理。因此,对于任何两个动作ab,要么a对b可见,要么ba可见,或者以上都不可见。Java 内存模型示例:Good、Bad 和 Ugly是理解格式良好的执行概念的好读物。

(3) 如果action_a没有在action_b之前发生,并且action_b在action_a之前没有发生,这是否意味着action_a可能看到或可能没有看到action_b?

是的,任何一个都是可能的。无论哪种方式都无法保证。

(4) 不可能有任何循环的happens-before,对吧?

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

于 2014-12-24T13:15:21.960 回答
2

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

A Happens before关系创建了一个内存屏障,阻止了 action-b 在 action-a 之前执行。因此无法应用一些底层 JVM 优化。因此,任何操作-a不能在操作-b 之后或与操作-b 一起执行。

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

这意味着action-b必须看到action-a带来的所有变化。

如果 action_a 没有发生在 action_b 之前,并且 action_b 没有发生在 action_a 之前,这是否意味着 action_a 可能会看到或可能不会看到 action_b?

Happens-before是一种传递关系。因此,如果 action-a 发生在 action-b 之前,而 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 可以先执行,前提是 final 等价于如果 action a 在 action b 之前执行的状态。这是特定于实现的。JIT 可能决定在操作 a 之前运行操作 b,前提是此顺序更改不会影响最终结果。

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

  2. 发生在指定的顺序动作之前。如果动作是并行的,那么发生之前不存在。

注意:所有这些混淆都是因为如果两个动作之间没有依赖关系,JIT会删除之前发生的事情。请阅读逃逸分析

于 2014-12-24T12:26:47.143 回答