求对ArrayBlockingQueue中一段源码的解释
为什么take()方法在判断队列中元素个数是否为0的时候使用了while循环,而不是if;
我认为,如果notEmpty.await()方法既然苏醒返回了 ,那么此线程肯定拿到了lock。
而苏醒的原因也是因为put()方法放入了新的元素,而其他线程无法拿到锁,自然无法取走元素,那么此时对于拿到锁的线程来说count肯定不为0了,应该放心的执行 dequeue()获取元素就可以了。
不知道作者使用了while是何意呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
先看
Condition.awit()
的源码:await
方法核心做了 3 件事情:所以 notEmpty.await() 方法既然苏醒返回了 ,那么此线程肯定拿到了 lock 这句话是正确的。
此时,我们假设
ArrayBlockingQueue
的take
方法使用的是if
:count == 0
时,有 2 个线程 A 和 B 都执行了notEmpty.await()
,且 A 和 B 都已经执行到了acquireQueued(node, savedState)
(即都处于 自旋等待 中,这时 A 和 B 都处于阻塞中)ArrayBlockingQueue
中添加了一个元素,接着执行notEmtpy.signal()
唤醒一个线程dequeue()
,然后线程 A 释放锁(这种情况没有问题)while
,所以此时不会再重新判断条件,从而继续向下执行dequeue()
导致出错所以在你这段代码里当前队列为空时(count==0),调用了
notEmpty.await()
,这段代码对锁是有影响的,实际上底层上已经释放了锁,只是这个方法保证了被唤醒时一定又能够拿回锁(当有元素放入队列会调用notEmpty.signal()
进行唤醒),那为什么需要使用while呢?因为insert后lock.unlock
,未必notEmpty.await()
立即被唤醒,可能之前插入一个线程运行remove方法