4

Java の事前発生と同期については、少し意見の相違があります。

次のシナリオを想像してください。

メインスレッド

MyObject o = new MyObject();    // (0)
synchronized (sharedMonitor) {
    // (1) add the object to a shared collection
}
// (2) spawn other threads

その他のスレッド

MyObject o;
synchronized (sharedMonitor) {
    // (3) retrieve the previously added object
}
// (4) actions to modify the object

のインスタンス変数はでも でもMyObjectないことに注意してください。のメソッドは同期を使用しません。volatilefinalMyObject

私の理解では、次のとおりです。

  • 1は 3の前に発生 します。これは、同じモニターで同期が行われ、他のスレッドが2でのみ生成され、 1の後に実行されるためです。

  • 4に対するアクションは、すべてのスレッドに対してさらに同期が行われ、メイン スレッドがこれらのアクションの後に何らかの方法で同期しない限り、後でメイン スレッドに表示されるという保証はありません。

Q: 0でのアクションが表示され、前に発生し、 3で同時アクセスされるという保証はありますか?それとも、変数を として宣言する必要がありますvolatileか?


ここで、次のシナリオを検討してください。

メインスレッド

MyObject o = new MyObject();    // (0)
synchronized (sharedMonitor) {
    // (1) add the object to a shared collection
}
// (2) spawn other threads, and wait for their termination
// (5) access the data stored in my object.

その他のスレッド

MyObject o;
synchronized (sharedMonitor) {
    // (3) retrieve the previously added object
}
o.lock();    // using ReentrantLock
try {
    // (4) actions to modify the object
} finally { o.unlock(); }

私の理解では、次のとおりです。

  • 1 前と同じように3の前に発生します。

  • が保持するでの同期により、 4でのアクションは他のスレッド間で表示されます。ReentrantLockMyObject

  • 4に対するアクションは論理的に3の後に発生しますが、別のモニターで同期した結果として、3から4への先行発生の関係はありません。

  • 4sharedMonitorの後unlockに同期があったとしても、上記の点は当てはまります。

  • メインスレッドが他のタスクの終了を待っている場合でも、4のアクションは5のアクセスの前に発生しません。これは、5へのアクセスが と同期されていないためです。そのため、メイン スレッドには古いデータがまだ表示される場合があります。o.lock()

Q:私の理解は正しいですか?

4

1 に答える 1