1

以下は、JMM の 3 つの「事前発生」ルールです。私の質問はこれら 3 つのルールのみに関連しているため、他のルールは記載していません。

  • ロック規則を監視します。モニター ロックのロック解除は、同じモニター ロックの後続のすべてのロックの前に行われます。
  • スレッド開始規則。スレッドでの Thread.start の呼び出しは、開始されたスレッドのすべてのアクションの前に発生します。
  • 中断ルール。別のスレッドで割り込みを呼び出すスレッドは、割り込みを受けたスレッドが (InterruptedException をスローするか、isInterrupted または interrupted を呼び出すことによって) 割り込みを検出する前に発生します。

質問

  1. 第 1 のルールの質問 - 2 つのスレッド A と B が同期したコード ブロックを持っているとします。最初のルールは、変数が volatile として宣言されていなくても、スレッド A の同期ブロックに設定された変数は、スレッド B の同期ブロックのコードから見えるということですか?

  2. 2 番目のルールの質問- スレッド A がスレッド B を開始するとします。2 番目のルールは、変数が volatile として宣言されていなくても、start() を呼び出す前に親スレッドに設定された変数がスレッド B に見えることを意味しますか?

  3. 3 番目の規則の質問- スレッド A がスレッド B に割り込むとしましょう。揮発性?

最後に、もう 1 つ質問します。

  1. BlockingQueue のドキュメントでは、次のように述べられています。

    メモリの一貫性の影響: 他の並行コレクションと同様に、オブジェクトを BlockingQueue に配置する前のスレッド内のアクションは、別のスレッド内の BlockingQueue からのその要素へのアクセスまたは削除に続くアクションの前に発生します。

これは、変数が揮発性として宣言されていなくても、オブジェクトをブロック キューに入れる前にスレッド A に設定された変数が、キューからオブジェクトをデキューした後にスレッド B に見えることを意味しますか?

基本的に上記の質問を通じて、これらの場合に変数を volatile として宣言する必要がないように、これらのイベントの後にメモリ フラッシュが発生するかどうかを理解しようとしています。

4

1 に答える 1

1

第 1 のルールの質問 - 2 つのスレッド A と B が同期したコード ブロックを持っているとします。

スレッドにはコードがありません。スレッドはコードを実行します。

最初のルールは、変数が volatile として宣言されていなくても、スレッド A の同期ブロックに設定された変数は、スレッド B の同期ブロックのコードから見えるということですか?

はい、次があるとします。

private int i;
private final Object lock = new Object();

void foobar(...) {
    ...
    synchronized(lock) {
        i = ...;
    }
}

int getI() {
    synchronized(lock) {
        return i;
    }
}

スレッド A がfoobar()を呼び出し、その後スレッド B が を呼び出しgetI()た場合、スレッド B は の新しい値を取得しますi

しかし、注意してください!上記の私の例には、どの呼び出しが実際に最初に発生したかを証明する方法は含まれていません。プログラムがこれらの呼び出しを特定の順序で実行することに依存している場合、mutex だけでなく、wait()スレッド A が更新を実行できるようにスレッド B を作成する何らかの手段が必要になります。


2 番目のルールの質問 - スレッド A がスレッド B を開始するとします。2 番目のルールは、変数が volatile として宣言されていなくても、start() を呼び出す前に親スレッドに設定された変数がスレッド B に見えることを意味しますか?

はい、そういう意味です。

3番目のルールの質問...

はい、また。

  1. ...ブロッキングキュー...

はい、また。


...上記の質問を通じて、これらのイベントの後にメモリフラッシュが発生するかどうかを理解しようとしています...

「メモリフラッシュ」についても考えないでください。これは Java 言語の一部ではありません。発生した場合、それは実装の詳細であり、JVMを実装していない限り、気にする必要はありません。

心配する必要がある唯一の概念は、「前に起こる」ということです。

JLS が Aが B の前に発生すると言うときは常に、 A がスレッド 1 で発生し、B がスレッド 2 で発生した場合、A が実際に B の前に発生したことをリアルタイムで証明できることを意味します。 A が発生する前のスレッド 1 は、B が発生した後にスレッド 2 で表示されることが保証されます。

于 2015-09-01T13:58:35.007 に答える