4

同期ブロックや揮発性変数がない場合、あるスレッドによって実行された書き込みが別のスレッドから見えるのはいつですか? 簡単なクイックソートの例を次に示します。

int middle = partitionForTheFirstTime(array);

Thread t = new Thread(new Quicksorter(array, 0, middle - 1));
Thread u = new Thread(new Quicksorter(array, middle + 1, array.size - 1));

t.start()
u.start();

t.join();
u.join();

(簡単にするために、2 つの「ワーカー スレッド」は追加のスレッドを生成しないと仮定します。)

2 つのスレッドを結合すると、現在のスレッドがすべての副作用を確認できることが保証されますか?


関連して、最初のパーティショニングのにスレッドを作成するとどうなりますか?

Quicksorter a = new Quicksorter();
Quicksorter b = new Quicksorter();

Thread t = new Thread(a);
Thread u = new Thread(b);

int middle = partitionForTheFirstTime(array);

a.setParameters(array, 0, middle - 1);
b.setParameters(array, middle + 1, array.size - 1);

t.start()
u.start();

t.join();
u.join();

2 つのスレッドは、によって引き起こされる副作用を確認できpartitionForTheFirstTime()ますか? つまり、スレッドを作成すると、事前発生の関係が発生しますか、それともスレッドを開始しますか?

4

2 に答える 2

8

JLS のセクション 17.4.5から:

上記の定義から、次のことがわかります。

  • モニターのロック解除は、そのモニターの後続のすべてのロックの前に発生します。
  • 揮発性フィールド (§8.3.1.4) への書き込みは、そのフィールドの後続のすべての読み取りの前に発生します。
  • スレッドでの start() の呼び出しは、開始されたスレッドのアクションの前に発生します。
  • スレッド内のすべてのアクションは、他のスレッドがそのスレッドの join() から正常に戻る前に発生します。
  • オブジェクトのデフォルトの初期化は、プログラムの他のアクション (デフォルト書き込み以外) の前に発生します。

start()とに関するビットjoin()は、関連するものです。つまり、join()スレッドを正常に処理すると、そのスレッドのすべてのアクションが表示されます。スレッドの場合start()、その新しいスレッドは、 を呼び出したスレッドで既に発生したすべてのアクションを認識しますstart()

編集: 「メモリ一貫性エラー」も参照してください。

于 2011-06-07T10:23:32.607 に答える
0

partitionForTheFirstTime() を実行する前に start() を実行しない限り、両方のスレッドが同じデータを処理します。ただし、この例では、これらの個別のスレッドに参照値を渡すという点で注意が必要です。配列値は、値によって渡されるプリミティブ値とは対照的に、参照によって渡されます。その結果、両方のスレッドがまったく同じテーブルで動作し、競合状態が発生する可能性があります

于 2011-06-07T11:03:14.727 に答える