1

たとえば、 r.wait() が機能することを知りたいですか? このコードで:

public class Buffer1<T> {
private T content;
private boolean empty;
private Object r = new Object();
private Object w = new Object();

public Buffer1() {
empty = true;    }

public Buffer1(T content) {
this.content = content;
empty = false;    }

public T take() throws InterruptedException {
synchronized (r) {
while (empty) {
r.wait();
}

synchronized (w) {
empty = true;
w.notify();
return content;
  }
 }
}

public void put(T o) throws InterruptedException {
synchronized(w) {
while (!empty) {
w.wait();
}

synchronized (r) {
empty = false;
r.notify();
content = o;
}

r.wait()、w.wait()、r.notify()、w.notify() はどのように機能しますか? また、これらは Synchronized(r) / Synchronized(w) とどのように連携するのでしょうか?

4

1 に答える 1

0

スレッドはグループで中断されません。何が起こるかというと、スレッドが同期ブロックまたはメソッドに入り、ロック (ここでは r または w) を取得し、ロックを取得したオブジェクトに対してスレッドが wait を呼び出すと、スレッドは中断され、wait と呼ばれるロックを解放し、そのロックの待機セットに追加されます。

ここには、wait の呼び出しをループで囲むパターンがあります。メソッドを呼び出すスレッドは、ループ内のテストが false になるまで待機し続ける必要があります。スレッドが待機から続行できる状態は、条件と呼ばれます。主に、通知されたスレッドがロックの所有権を持っていないため、待機メソッドがループで呼び出されます。ロックを再取得したら、現在の状態をテストする必要があります。

そのロックで notifyAll を呼び出すことにより、ロックの待機セット内のすべてのスレッドを起動します。実際には、これは最適ではありません。通常、一度にロックを取得して進行できるスレッドは 1 つだけだからです。notifyAll の使用は、同じロックを求めて競合するスレッドが異なる条件を待機している可能性があり、通知が一部のスレッドに関係のない状態である可能性がある場合に発生します。通知を使用すると、(スケジューラの気まぐれで選択された) 1 つのスレッドのみが起動されます。スレッドが待機している状態が通知の目的ではない場合、通知は失われ、スレッドは進行しません。notifyAll を使用すると、通知がいずれかのスレッドに適用される場合、そのうちの 1 つが処理を進めることができます。どちらが代替案を打ち負かし、

投稿されたコードでは、条件ごとに個別のロック オブジェクトを使用することで、notifyAll の使用を避けることを意図しているようです。オブジェクト r には、バッファーが空でなくなるまで待機するスレッドがあり、オブジェクト w には、バッファーが空になるまで待機するスレッドがあります。そうすれば、通知が呼び出されたときに、通知が関連するスレッドを確実に起こすことができます (置くのを待っているスレッドのみを によって起こすことができますw.notify())。

このコードの問題は、put 操作と take 操作が両方のロックを取得し、それらが互いに逆の順序で取得することです。これは、デッドロックを引き起こすための本当に良い方法です。同期されたキーワードと固有のロックでは、タイムアウトしてバックオフする方法がなく、回復する良い方法はありません。あるスレッドが r を持っていて w を必要としているのに対し、別のスレッドが w を持っていて r を必要としている場合は、行き詰まります。それぞれがロックを保持している 2 つのスレッドは処理を進めることができず、他のスレッドはどちらのロックも取得できないため、このバッファーのメソッドに入ろうとするすべてのスレッドが、JVM を強制終了するまでブロックされます。

于 2017-01-10T05:06:51.703 に答える