1. ホーム
  2. java

[解決済み] java.util.concurrent.locks.Condition はどのように機能するのですか?

2022-03-02 05:53:26

質問

Java 8 のドキュメントを読むと java.util.concurrent.locks.Condition インターフェイスを使用する場合、次のような例が挙げられます。

class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)
         notFull.await();
       items[putptr] = x;
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
 }

そこで一番の疑問は、「条件とはどのように機能するのか」ということです。

  1. 待ちが始まるとロックを解除するのですか?( notFull.await() など)?
  2. 異なるスレッドが同じロックを取得し、そのロックが解除されるまで移動することは可能か? signal() 条件を満たすと、他のスレッドが目を覚ましますか?
  3. この例では、あるスレッドがバッファを待っていると、デッドロックになると思いました。 空でない 他のスレッドがロックを取得し、バッファを空にすることはできません。 signal() 条件を満たしたので、ロックを解放します。 バッファが一杯にならないのを待つスレッドによってロックが解放されていない場合 ?

これらは初心者の質問です。よろしくお願いします。

ありがとうございました。

解決方法は?

  1. はい、その通りです。条件を待つとすぐにロックを解除します。 await/signal/signalAll と同じ挙動をします。 wait/notify/notifyAll
  2. ReentrantLock は排他的ロックなので、1 つのスレッドだけがロックを取得できます。
  3. 1を参照してください。スレッドが signal または signalAll を待っているスレッドまたはすべてのスレッドをそれぞれ解放します。 Condition そのため、そのスレッドまたはそれらのスレッドは、再びロックを取得する資格があります。しかし今のところ、ロックはまだ signal または signalAll を呼び出して明示的にロックを解放するまで。 lock.unlock . その後、解放されたスレッドは再びロックを取得しようとすることができ、ロックを取得できたスレッドは再び条件を確認することができます (今回、条件とは count == items.length または count == 0 この例では)、もしそれが問題なければ、それは続行されます。 await を再度実行し、ロックを解放して他のスレッドで利用できるようにします。