在Java中,我们可以将最终的重新排序规则视为发生在之前的规则吗?

huangapple go评论54阅读模式
英文:

Can we treat final reorder rule in Java as happens-before rule?

问题

在Java中存在两个最终记录规则,如下所示:

  1. 在构造函数中对最终字段进行写入,并且随后将构造的实例引用分配给变量,这两者不能被重新排序。
  2. 读取实例引用,并随后读取实例中的最终字段,这两者不能被重新排序。

我们可以将上述规则视为happen-before规则吗?

  1. 在构造函数中对最终字段进行写入 发生在 构造的实例引用被分配给变量之前。
  2. 读取实例引用 发生在 读取实例中的最终字段之前。

我认为happen-before规则具有更强的语义。

英文:

There exist two final record rules in Java, as follows:<br/>

  1. a write to final field in constructor and the constructed instance reference is assigned to variable afterwards can not be reordered
  2. read a instance reference and read the final field in the instance afterwards can not be reordered

Can we treat above rules as happen-before rules?

  1. a write to final field in constructor happens-before the constructed instance reference is assigned to variable afterwards
  2. read a instance reference happens-before read the final field in the instance afterwards

I think happens-before rule is stronger semantic.

答案1

得分: 0

在我理解中,最终关键字的语义保证和先行发生规则属于不同的类别。上述推导是错误的,也是不必要的。

英文:

In my understanding finally,the semantic guarantee of final keyword and happens-before rule belong to separate categories.The above derivation is wrong and unnecessary.

答案2

得分: 0

我认为先于发生规则更具有强大的语义。

在这个上下文中,最终的重新排序规则明显更强大:

  • 先于发生规则并不禁止本地语句的重新排序,前提是重新排序后的行为是顺序一致的;即仅从创建对象的线程的角度来看。

  • 相比之下,最终的重新排序规则确实明确禁止构造函数内部的某些重新排序,除了那些会违反顺序一致性的重新排序。

推论:HB(先于发生)并不包含最终的重新排序规则。

(如果包含的话,就根本不需要在后面陈述最终规则。但是JLS(Java语言规范)的作者们并不是为了无意义地添加这些内容。请给予他们以及其他成千上万阅读/学习过这些内容的人一些认可。)


设计目标是,应该可以在任何线程中使用final字段,而无需任何显式的同步或与内存模型相关的性能开销;即读取时不需要内存屏障。

如果在构造函数中允许对final字段进行本地重新排序,那么另一个线程需要一个内存屏障,以确保它看到受影响字段的一致值。我想不出一种实际的优化方法来消除这种影响。在构造函数中不重新排序的潜在小影响(平均而言)要小于每次读取字段时的读取屏障的影响。

英文:

> I think happens-before rule is stronger semantic.

The final reordering rule is definitely stronger, in this context:

  • The happens-before rule does not forbid reordering of statements locally provided that the behavior after reordering is sequentially consistent; i.e. solely from the perspective of the thread creating the object.

  • By contrast the final reordering rule does expressly forbid certain reorderings within the constructor, in addition to those the would violate sequential consistency.

Corollary: the HB doesn't subsume the final reordering rule.

<sup>(If it did, then it wouldn't be necessary state the latter at all. But the JLS authors don't add that stuff just for the heck of it. Give them and the thousands of other people who have read / studied this stuff some credit.)</sup>


It is a design goal that it should be possible to use a final field from any thread without any explicit synchronization or memory model related performance overheads; i.e. no memory barriers for reads.

If local reordering for a final fiels was permitted in the constructor, then another thread would need a memory barrier to ensure that it saw a consistent value for the affected field. I can't think of a practical way to optimize that away. The potential small impact of not reordering in a constructor is (on average) less than the impact of read barrier for every read of the field.

huangapple
  • 本文由 发表于 2020年7月27日 12:00:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/63108506.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定