1

JAVAの同期と最終の関係を知りたいです。私はいくつかの記事を読みましたが、コンストラクターで最終フィールドを使用してオブジェクトを初期化する必要があると誰もが言及しています。そうしないと、初期化されていないオブジェクトが同じオブジェクトを使用する複数のスレッド間で同期の問題を引き起こす可能性があります。

為に。たとえば、以下のコード:

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;
    int j = f.y;
  }
 }  
}

リーダーは x の値を正しく読み取ることができますが、最終宣言されていないため、y の値を 0 として読み取ることがあります。

なぜこうなった?

4

2 に答える 2

2

これは、最終フィールドのセマンティクスに関係しています。JLS #17.5は良い要約を提供します:

final フィールドの使用モデルは単純です。オブジェクトのコンストラクタでオブジェクトの final フィールドを設定します。オブジェクトのコンストラクターが終了する前に、別のスレッドが参照できる場所に構築中のオブジェクトへの参照を書き込まないでください。これに従えば、オブジェクトが別のスレッドから見られるとき、そのスレッドは常に、そのオブジェクトの final フィールドの正しく構築されたバージョンを認識します。

言い換えれば、this構築中にエスケープさせなければ、すべてのスレッドが x の正しい値 (つまり 3) を認識することが保証されます。

もう一方のフィールド (y) については、同期が行われない場合、どの値が表示されるか (デフォルト値またはコンストラクター値) が保証されません。

于 2013-02-24T00:20:37.327 に答える
-1

finalフィールドは、スレッド化とはほとんど関係ありません。volatileあなたが説明したように少し動作するフィールドを考えていると思います。

于 2013-02-24T00:28:56.840 に答える