これは、主に Java の並行性に関する質問です。Scala 並行性は Java 並行性モデルの上に構築されていますが、構文が異なります。Scala では、synchronized
は のメソッドでAnyRef
あり、上記の構文は、キーワードを使用して次の Java コードのように同期メソッドsynchronized
を記述することと同じです。
public class PC {
public int buffer;
public boolean set;
public synchronized void produce(int value) {
while(set) wait();
buffer = value;
set = true;
notify();
}
public synchronized int def consume {
while(!set) wait();
int result = buffer;
notify();
return result;
}
}
Java 並行性モデルの詳細については、Java チュートリアルを参照してください。Java Concurrency Libraryを調査することをお勧めします。たとえば、容量が 1のブロッキング キューを使用して同じことを実装できます。
あなたの質問に答えて:
1. notifyAll の代わりに notify を使用すると、デッドロックに陥ります。生産または消費のために、どこでnotifyAllを使用する必要がありますか?
プロデューサー スレッドではなく、他のコンシューマー スレッドによって受信されるため、(デッドロックではなく) 競合状態が発生している可能性がありますが、それは単なる推測notify()
です。orconsumer()
を使用するかどうか、およびどのメソッドで使用するかについては、常に使用することを推奨する人もいます。そして、この場合、条件付き while ループで待機しているため、 を使用できます。これは、 wait()のドキュメントで説明されているさまざまな理由で常に実行する必要があります。ただし、の最適化としてを使用することもできます。これは、1 つのコンシューマーのみがバッファーの内容を消費することを想定しているためです。現在の実装では、引き続き使用する必要がありますnotify()
notifyAll()
notifyAll()
notifyAll()
notify()
producer()
notifyAll()
consume()
または、単一の待機中のプロデューサーではなく、コンシューマーの 1 つに通知され、その結果、プロデューサーが永遠に待機する状況にさらされる可能性があります。
2. lock などのオブジェクトを持っていて、lock.synchronized、lock.wait、および lock.notify を呼び出すべきではありませんか? 2 つの異なるモニターを関連付けて生成および消費しないのはなぜですか? 生産からの「通知」が消費からの「待機」通知を行うのはなぜですか?
あなたはロックを持っています。これはインスタンスに対する暗黙のロックでPC
あり、Java ではオブジェクトごとに 1 つだけのモニターがありますが、多数のエントリ ポイントが存在する可能性があります。wait()
inはinconsume()
によって通知されます。これは、どちらも同じリソース (インスタンス) のロックを待機しているためです。より柔軟できめ細かなロックを実装する場合は、LocksなどのJava Concurrency Libraryのさまざまな戦略を使用できます。notify()
produce()
PC
3. モニターは scala で正確にどのように機能しますか (私たちの場合)? シグナルアンドコンティニューポリシーを使用していますか? 特定の条件で待機中のキューからプロセスを実行可能なキューに移動するにはどうすればよいですか? 条件/ロックごとにキューがありますか (lock1.wait、lock2.wait など)。
JVM がスレッド同期を実行する方法の詳細については、Java 仮想マシンがスレッド同期を実行する方法 を参照してください。同じ著者の章の詳細については、Inside the Java Virtual Machineを参照してください。