JMM 中 final 字段的语义

use*_*448 5 java concurrency multithreading

这里 [ http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5][1]

它说:

给定写入 w、冻结 f、动作 a(不是读取最终字段)、读取由 f 冻结的最终字段的 r1 和读取 r2 使得 hb(w, f), hb( f, a)、mc(a, r1) 和 dereferences(r1, r2),那么在确定 r2 可以看到哪些值时,我们考虑 hb(w, r2)。(这种发生在排序之前不会与其他发生在排序之前传递关闭。)

他们想在这里说什么?我知道 r2 只是读取 r1 读取的最终字段值,因此很明显 hb(w, r2),因为 r1 读取了此变量的正确版本,因为该值被 f 冻结。或者他们的意思不同?多深?此外,他们想说这个 hb 订购不会与其他 hb 订购“传递关闭”?

Mar*_*nik 4

r1读取由 写入的值这一唯一事实w甚至不意味着这一点hb(w, r1),更不用说hb(w, r2)。反之亦然:如果和 之间存在happens-before关系,那么JMM保证将观察到什么值;否则无法保证。如果确实观察到 的值,则这只是一个巧合,并且不会事后诱发发生之前的关系。wr1r1w

想象一个重要示例的最佳方式是通过数据竞争安全发布的用例。对 a 的引用String会在不同步的情况下写入非易失性字段,然后从另一个线程取消引用该字段。如果线程碰巧观察到String(不保证它会),则可以保证线程将看到String处于一致状态。

如果没有额外发生之前的特殊规定(仅在您的报价所描述的精确情况下才考虑),则无法保证将String完整地观察到。

他们想说的是,此 HB 订购不会与其他 HB 订购“传递关闭”?

通常,hb(a,b)hb(b,c)意味着hb(a,c),但这种传递性不适用于由于字段冻结而存在的特殊发生之前。这些特殊的happens-before有自己的“命名空间”。