synchronizedブロックは、コードスレッドを安全にします。より効率的にするには、wait()
とnotify()
またはnotifyAll()
を使用します。
たとえば、共有リソースがリストの場合、複数のスレッドが共有します。モニタの同期ブロックに入れると、スレッドはコンテキストスイッチ中に常にジャンプしてコードを実行します。リストが空であっても!
wait()
は、従ってリラックスし、さらに通知又はnotifyAll()
までCPUサイクルの使用を停止するすべてのスレッドを「伝える」ための機構として、モニタ(synchronized(..)
内部オブジェクト)に使用されます。上記の例で
synchronized(monitor) {
while(list.isEmpty())
monitor.wait();
doSomething(...)
}
別のスレッドがコード内の他notify()
notifyAll()
又はどこかを実行した後に、doSomething()
は、リストが空でないだけを実行します。
が、以下のコードで:
- :
synchronized(monitor) {
if(!list.isEmpty())
doSomething(...)
}
スレッドが同期ブロックに入って来、3つの可能なシナリオがありますリストは空です:doSomething()
wil私は実行されません。
- リストは空ではありません:
doSomething()
が正しく実行されるか、または...
if
の直後でdoSomething
の前にコンテキストスイッチがあり、もう1つのスレッドがすべてのリストのアイテムを取り出した場合、別のコンテキストスイッチアウトスレッドの後に空のリストにdoSomethig()
が実行されます。
したがって、すべてを集計するために、wait/notifyを使用すると、より効率的なコードが保証されます。スレッドは必要ないときには動作しません。
比較しようとしているコードを表示できますか? – Joni
これらの概念は矛盾していません。実際には、条件が既に満たされている場合は、待つ前に常に条件をチェックしておく必要があります。そうしないと永遠に待つことになります。一方、条件が満たされない場合、ループを介して正常にポーリングすることは不可能です。これは、条件を変更するときに他のスレッドが適切に 'synchronized'を使用しなかったことを示すためです。重要なポイントは、一時的にモニタを解放し、別のスレッドが待っている状態を変更する 'synchronized'コードを入力できるようにすることです。 – Holger