1

Java中存在两条最终记录规则,如下:

  1. a write to final field in constructor并且the constructed instance reference is assigned to variable afterwards不能重新排序
  2. read a instance reference并且read the final field in the instance afterwards不能重新排序

我们可以将上述规则视为发生之前的规则吗?

  1. a write to final field in constructor发生之前the constructed instance reference is assigned to variable afterwards
  2. read a instance reference发生之前read the final field in the instance afterwards

我认为发生在规则之前的语义更强。

4

2 回答 2

0

最后,在我的理解中,final关键字和happens-before规则的语义保证属于不同的类别。上述推导是错误的和不必要的。

于 2020-11-26T02:55:17.163 回答
0

我认为发生在规则之前的语义更强。

在这种情况下,最终的重新排序规则肯定更强:

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

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

推论:HB 不包含最终的重新排序规则。

(如果是这样,那么根本没有必要说明后者。但是 JLS 的作者不会仅仅为了它而添加这些东西。给他们和成千上万的其他阅读过/研究过这些东西的人一些信用。)


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

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

于 2020-11-26T03:49:37.703 回答