ホームページ  >  に質問  >  本文

java - ArrayBlockingQueue のソース コードの説明を探しています

take() メソッドがキュー内の要素の数が 0 かどうかを判断するときに if ではなく while ループを使用する理由;

リーリー

目が覚める理由は、put() メソッドが新しい要素を入れるためでもあり、他のスレッドはロックを取得できないため、当然要素を奪うことはできません。 、カウントは決して 0 ではありません。要素を取得するには、自由に dequeue() を実行してください。
作者が while を使用する意味がわかりません。

阿神阿神2702日前834

全員に返信(2)返信します

  • 漂亮男人

    漂亮男人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 ページ) を参照してください。

    返事
    0
  • 黄舟

    黄舟2017-05-27 17:43:19

    リーリー

    そのため、コード内の現在のキューが空 (count == 0) の場合、 notEmpty.await(),这段代码对锁是有影响的,实际上底层上已经释放了锁,只是这个方法保证了被唤醒时一定又能够拿回锁(当有元素放入队列会调用notEmpty.signal()进行唤醒),那为什么需要使用while呢?因为insert后lock.unlock,未必notEmpty.await() の呼び出しによってすぐに起動されます。

    の前に、削除メソッドを実行するスレッドを挿入できます。

    返事
    0
  • キャンセル返事