synchronized
私は次のようなブロックを書いていました:
synchronized(foobar) {
// do something
}
しかし、最近、誰かが次のように書いているのを見ました。
synchronized(foobar) {
// do something
foobar.notifyAll();
}
foobar.notifyAll();
必要ですか?省略したらどうなりますか?
synchronized
私は次のようなブロックを書いていました:
synchronized(foobar) {
// do something
}
しかし、最近、誰かが次のように書いているのを見ました。
synchronized(foobar) {
// do something
foobar.notifyAll();
}
foobar.notifyAll();
必要ですか?省略したらどうなりますか?
短い答えは、それはあなたが何をしているかに依存するということです。
同期ブロックの目的が、データ構造へのアクセス/更新が安全に実行されるようにすることだけである場合、notify()
またはnotifyAll()
目的を果たしません。
一方、目標が「条件変数」を実装することである場合、notify()
ornotifyAll()
呼び出しは次のwait
ような呼び出しで機能します...例:
private boolean flag;
private final Object mutex = new Object();
public void awaitFlag(boolean flag) {
synchronized (mutex) {
while (this.flag != flag) {
mutex.wait();
}
}
}
public void setFlag(boolean flag) {
synchronized (mutex) {
this.flag = flag;
mutex.notifyAll();
}
}
上記は、 がまたはになるawaitFlag()
のを待機するためにスレッドが呼び出す単純なメカニズムを実装しています。別のスレッドがフラグを変更するために呼び出すと、現在フラグが変更されるのを待っているすべてのスレッドが によって起こされます。これは、コードの動作に が不可欠な例です。flag
true
false
setFlag()
notifyAll()
notifyAll()
notify
またはnotifyAll
コードが必要かどうかを理解するには、他のコードがwait
同じミューテックス/ロック オブジェクトを呼び出す可能性があるかどうかを判断する必要があります。
これを行う必要はありません。foobar
オブジェクト (ここでは ) が通知を待っている場合にのみ実行する必要があります。通知のみこのオブジェクトのモニターで待機しているすべてのスレッドを起こします。
Java では、 と を使用wait()
しnotify()
て、notifyAll()
スレッドの調整を実現できます。Javaでwaitとnotifyを使用する方法を参照してください。
notifyAll() は、foobar.wait() でスリープしている他のスレッドに、現在のスレッドがロックを解放しようとしていることを伝え、リソースを再び競合できるようにします。