2

私はJavaのに少し混乱していますnotify()。次の例は教科書からのものです。

public synchronized consume() {
    while(queue.isEmpty()) {
        try{ wait(); } catch (InterruptedException e) {}
    }
    // Assume that getElement() notifies to producers.
    element = queue.getElement();
    ...
}

public synchronized produce() {
    while(queue.isFull()) {
        try{ wait(); } catch (InterruptedException e) {}
    }
    element = new Element();
    ...
    queue.addElement(element);
    notifyAll();
}

produce()上記の例の方法はよく理解しています。notifyAll()しかし、最初の方法()の最後に使用しない理由を誰かに教えてもらえますconsume()か?要するに、なぜこれが好きではないのですか?

public synchronized consume() {
    while(queue.isEmpty()) {
        try{ wait(); } catch (InterruptedException e) {}
    }
    // Assume that getElement() notifies to producers.
    element = queue.getElement();
    ...
    notifyAll();
}

どうもありがとう!

よろしくお願いします。

4

2 に答える 2

6

@Slashに同意します。コード例では、キューから要素を削除しているため、誰かがisEmpty()ループで待機しているプロデューサーに通知する必要があります。ただし、コードは次のように述べています。

// Assume that getElement() notifies to producers.
element = queue.getElement();

したがって、そのコメントは何らかの形でorをgetElement()呼び出すことを意味します。notify()notifyAll()

要するに、なぜこれが好きではないのですか:

はい、コメントを削除する必要がありますが、コードは機能します。:-)

通常、これらのプロデューサー/コンシューマー パターンでは、2 つのロックがあります。1 つはキューが空の場合で、もう 1 つはキューがいっぱいの場合です。次に、キューが満杯でなくなったときにコンシューマーがプロデューサーに通知、他のコンシューマーをウェイクアップしないようにすることができます。この場合も、notify()1 つのコンシューマーまたは 1 つのプロデューサーのみを目覚めさせる必要があるため、single を使用できます。notifyAll()オンになっているオブジェクトが 1 つしかないため、ここでは が使用されていsynchronizedます。

また、後世のために、ループがステートメントではないことに気付くことが非常に重要です。2 つのロックを使用している場合でも、保護する必要がある複数のプロデューサー/コンシューマー モデルで競合状態が発生します。また、偽のウェイクアップも問題です。詳細はこちら:while() ifnotify()

http://256stuff.com/gray/docs/misc/producer_consumer_race_conditions/

于 2012-04-12T00:37:44.447 に答える
1

この場合、生成時に通知が使用され、消費者の 1 人が目を覚ましてそれを消費できるように、消費するものがあることを消費者に伝えます。

コンシューマが何かを消費したときの通知は、getElement() 内で発生すると想定されます。

// Assume that getElement() notifies to producers.
于 2012-04-12T00:37:36.373 に答える