3

2 つのコード ブロックがあり、一方は他方が通知するのを待ちます。

synchronized(this) {
    wait();
}

while(condition) {
    //do stuff
    synchronized(this) {
        notify();
    }
}

奇妙なことに、これが通知を待たなかったのは次のとおりです。

synchronized(objectLock) {
    objectLock.wait();
}

while(condition) {
    //do stuff
    synchronized(objectLock) {
        objectLock.notify();
    }
}

両方のセットの違いと、最初のセットが機能し、他のセットが機能しなかった理由について非常に興味があります。2 つのブロックが 2 つの異なるメソッドの 2 つの異なるスレッドに存在することに注意してください (それが役立つ場合)。

なぜそうなのか誰かが説明してくれることを願っています。より詳細になるように、質問を編集しました。

4

4 に答える 4

2

好きなオブジェクトを使用できます。ただし、一般に、他のプログラマーにとっては、明示的なロック オブジェクトを確認する方が明確です。

なぜthisうまくいかなかったのかについての私の推測ではthis、スコープが異なっていたということです。(つまり、無名関数/コールバック内)。クラス名を追加することで、これを使用することを明示できます。たとえば、これも明確ではないWonderClass.this理由thisです。(編集:本当に別のインスタンスであるWhateverClass.this場合、実際には役に立ちません)this

これも読んでください: http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html - 一般的に、すべてのスレッドセーフでないコードを小さな同期メソッド (暗黙のロックを行う) に入れる方が簡単だと思います。これについて)

于 2013-05-23T14:26:54.953 に答える
2

2 つの異なるオブジェクトを指している 2thisつの異なるスレッドで同期したため、機能しませんでした。 Thread

wait()ととの同期は、後で使用したnotify()のようにロックするために同じオブジェクトで同期する場合にのみ適切に機能します。objectLock

編集: 2 つのスレッド インスタンスが同じクラスに属している場合、MyThreadコードが持っていると思っていた効果を得るには、クラス オブジェクト自体のロックを取得する必要があります。

synchronized(MyThread.class)
于 2013-05-23T14:33:16.853 に答える
1

2 つのブロックが 2 つの異なるスレッドにあると言うと、同じオブジェクトでthisはないため、同じオブジェクトをロックしていないと思います。明示的なロックに名前を付けると、同じものを使用してロックします。

ちなみに、次のようwaitにループで呼び出す必要があります。

synchronized(someLock) {
   while (!someCondition) {
       wait();
   }
   // now the thread has the lock and it can do things 
   // knowing for sure that someCondition is true
}

これがないと、偽のウェイクアップに対して脆弱になり (すべての通知がアプリケーション コードから送信されるわけではありません)、waitnotifyが呼び出される順序が問題になります (2 つのスレッドがあり、一方が待機する前に一方が通知される場合、その通知は表示されません)。

于 2013-05-23T14:35:04.840 に答える