2

私は BlockingQueue を書いていますが、他の実装がこの問題をどのように解決するのか疑問に思っています:

モニター (キュー オブジェクト) が 1 つしかなく、プロデューサーとコンシューマーを許可する場合、代わりに呼び出されるwaitことを確認する必要があります。そうしないと、プロデューサーは、キューがいっぱいの場合でも、別の待機中のプロデューサーに続行するように通知するだけです。物が入手可能であっても消費者を待たせる。一方、呼び出しは、多くのスレッドやプロセッサにとってスケーラブルなソリューションではないようです。notifyAllnotifynotifyAll

BlockingQueueは 2 台のモニターを使用しますか? 1 つは生産者の待機で、もう 1 つは消費者の待機でしたか? 次に、キューと関連するモニターをカプセル化された方法で同期する必要があります。それは行く方法ですか?

4

2 に答える 2

4

でどのように行われるかはわかりませんが、考えられる解決策の1 つは、 の代わりにBlockingQueueを使用することです。ReentrantLocksynchronized

と同じセマンティクスを持ちますsyncrhonizedが、いくつかの改良が加えられています。wait特に、他のスレッドがオンにできるいくつかの条件を持つことができます。

public class MyBlockingQueue<E> {
    private Lock lock = new ReentrantLock();
    private Condition notEmpty = lock.newCondition();
    private Condition notFull = lock.newCondition();

    public void put(E e) {
        lock.lock();
        try {
            while (isFull()) notFull.await();
            boolean wasEmpty = isEmpty();
            ...
            if (wasEmpty) notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public E take() {
        lock.lock();
        try {
            while (isEmpty()) notEmpty.await();
            boolean wasFull = isFull();
            ...
            if (wasFull) notFull.signal();
            ...
        } finally {
            lock.unlock();
        }
    }
    ...
}
于 2011-10-29T11:58:45.653 に答える
0

一般に、 を使用する方法notifyAll()は、 を使用する方法よりも優れていnotify()ます。おっしゃったように、読み取りアクセス用と書き込みアクセス用の 2 つの監視オブジェクトを使用できます。
代わりに使用notify()するとエラーが発生する可能性があり、使用によるパフォーマンスの低下はほとんどの場合無視できます。通常、待機中の各スレッドは偽のウェイクアップnotifyAll()に備える必要があるため、通常は別のコーディングは必要ありません。

于 2011-10-29T12:04:17.453 に答える