Java 仕様17.5には、Java メモリ モデルでの final フィールドの使用を示す次のコードがあります。(通常のフィールドと比較して)
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
}
}
}
仕様は次のように続けています。
「クラス FinalFieldExample には、最終的な int フィールド x と非最終的な int フィールド y があります。1 つのスレッドがライター メソッドを実行し、別のスレッドがリーダー メソッドを実行する可能性があります。オブジェクトのコンストラクターが終了した後にライター メソッドが f を書き込むため、リーダー メソッドはfx の適切に初期化された値が表示されることが保証されます: 値 3 が読み取られます。ただし、fy は最終的なものではないため、リーダー メソッドは値 4 を表示することが保証されていません。"
私の質問は次のとおりです。これは不十分な(または少なくともひどく不自然な)例ではありませんか または、ここで何か不足していますか?
この例を「ラメ」と呼ぶ理由は次のとおりです。
FinalFieldExample クラスのオブジェクトがマルチスレッド シナリオでスレッドによって共有される場合、何らかの形式の同期を使用するというマルチスレッドの基本原則に従うべきではありません。彼らが同期を使用していた場合、言及された問題は存在しませんでした。
上記の例は、適切な同期手法の代替 (または部分的なおしゃぶり) として Final フィールドを提唱しているようです。私の理解では、最終フィールドは、適切な同期の上で使用された場合でも使用されます。また、例で説明した利点を得るために使用しないでください (同期がない場合)。
通常のフィールドに対する final フィールドの利点を説明する適切な例 (同期を使用) はありませんか? たぶん、不変性です!