1

Jack Shirazi によるJava Performance Tuningでは、次のように書いています。

これは、変数のアクセスと更新が自動的に同期されることを意味します (変数が long または double でない限り)。メソッドが変数へのアクセスまたは代入だけで構成されている場合、スレッド セーフのために同期化する必要はなく、パフォーマンスのためにそうしない理由もあります。スレッド セーフは、他の変数値とは関係なく、変数にアクセスしたり、変数に代入したりするステートメントのセットにさらに拡張されます。

上記の説明によると、操作 likeflag = trueは常にアトミックであり、 は必要ありませんsynchronize

ただし、次の状況をデータ競合と見なす別の記事があります。


class DataRaceExample {
  static boolean flag = false;//w0
  static void raiseFlag() {
    flag = true;//w1
  }
  public static void main(String... args) {
    ForkJoinPool.commonPool().execute(DataRaceExample::raiseFlag);
    while (!flag);//r_i, where i ∈ [1, k), k may be infinite
    System.out.print(flag);//r
  }
}

そして著者は次のように述べています。

現在、フラグは揮発性ではないため、すべての実行にデータ競合があります

2 つの記事の矛盾について、私はかなり混乱しました。

4

3 に答える 3

1

2 番目の例では、ループは実行されないか、永久に実行されます。

これは、変数 flag が最初にチェックされるときに一度だけ読み取られるためです。

フラグが揮発性の場合、毎回メモリから読み取られます。これにより、別のスレッドが flag の値を変更できるようになり、ループはそれを認識します。

于 2019-12-29T04:16:53.963 に答える