「最終」に関連する保証についてJMMに言及したとき、私は最近混乱しました。JMM からの抜粋と例を次に示します。
図 4 は、最終フィールドが通常のフィールドとどのように比較されるかを示す例を示しています。クラス FinalFieldExample には、最終的な int フィールド x と非最終的な int フィールド y があります。1 つのスレッドが writer() メソッドを実行し、別のスレッドが reader() メソッドを実行する場合があります。オブジェクトのコンストラクターが終了した後に writer() が f を書き込むため、reader() は fx の適切に初期化された値を確認することが保証されます。つまり、値 3 を読み取ります。ただし、fy は最終的なものではありません。したがって、reader() メソッドが値 4 を表示することは保証されていません。
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
私の混乱は、オブジェクト「Obj」が最終フィールドと非最終フィールドを持ち、完全に初期化され、スレッド「T」によって参照されていることです.Tは最終フィールドの正しい値のみを参照しますか? 構築後に変更されない非最終フィールドはどうなりますか。構築スレッド 'T' の後にそれらが変更された場合、新しい値が表示されない可能性があることを理解しています (フィールドが volatile でない限り)。しかし、フィールドが非最終的かつ非揮発性であり、構築後に変更されていない場合はどうなりますか?
JVM は 'final' に関連付けられた保証をどのように実装しますか? たとえば、volatile にはメモリバリアがあります。