take() メソッドがキュー内の要素の数が 0 かどうかを判断するときに if ではなく while ループを使用する理由;
リーリー
目が覚める理由は、put() メソッドが新しい要素を入れるためでもあり、他のスレッドはロックを取得できないため、当然要素を奪うことはできません。 、カウントは決して 0 ではありません。要素を取得するには、自由に dequeue() を実行してください。
作者が while を使用する意味がわかりません。
漂亮男人2017-05-27 17:43:19
「notEmpty.await() メソッドが起動して戻るので、このスレッドはロックを取得しているはずです。」 この文は正しいです。
次のようなコードを書くとします:
リーリー 1 つ明らかなことは、それが return dequeue()
之前需要满足的一个条件是 count != 0
。我们假设 线程A 此时拿到了 lock,那么 线程A 的 notEmpty.await()
此时便会停止阻塞,准备向下执行 return dequeue()
。但是假设在竞争激烈的条件下,线程A 拿到 lock 之后,准备执行下一条 JVM 指令的时候,线程B 此时抢占了 lock,然后继续向下执行 return dequeue()
,刚好使得 count 变为了 0;而此时因为写的只是 if(count == 0)
,那么线程 A 在拿到 lock 之后,还是会继续向下执行 return dequeue()
にあることを確認する必要があり、それがエラーの原因となるということです。
条件が満たされない場合にブロックするこの方法が wait()
、await()
while ループ内で使用されなければならない理由については、『Effective Java』第 2 版の第 69 条 (244 ページ) を参照してください。
黄舟2017-05-27 17:43:19
リーリー
そのため、コード内の現在のキューが空 (count == 0) の場合、 notEmpty.await()
,这段代码对锁是有影响的,实际上底层上已经释放了锁,只是这个方法保证了被唤醒时一定又能够拿回锁(当有元素放入队列会调用notEmpty.signal()
进行唤醒),那为什么需要使用while呢?因为insert后lock.unlock
,未必notEmpty.await()
の呼び出しによってすぐに起動されます。