juc中ArrayBlockingQueue为什么出入用同一个锁?

昨天突然想到一个问题,为什么juc中ArrayBlockingQueue用一个锁(两个condition),而LinkedBlockingQueue用两个锁(两个condition)实现。

这导致了后者可以一边取一边放,而前者不行。

为了探究其设计的原因,产生了如下qa(自己和自己)

Q:为什么ArrayBlockingQueue put和take不能并行?

A:因为put 和 take用同一个reetrantlock实现。

Q:那改成两个reetranLock就可以并行take和put了吗?

A:不行。因为其中count是int而不是AtomicInteger。会因为和无法原子性修改以及编译器重排序导致其他问题。

Q:那修改int成AtomicInteger就可以了吗?

A:。。。大概吧。。。

   (实践尝试后。。)

    还是不行,因为这样通知的方式也要该,不能直接condition.signal()而要先获得另外一把锁再通知。

Q:那现在可以并行存取了吗?

A:可以了。

Q:那这样修改后效率有提高吗?

A:我试一下。。。(艾玛 太蛋疼了 周一去公司试好了 宿舍的破电脑 哎。。。)

    我先猜测,应该没有提高吧(douglea脑残粉- -哈哈哈)

Q:假设没有提高,你觉得原因是什么呢?
A:LinkedBlockingQueue的较大一部分时间需要构造节点,导致较长的等待。所以同时存取有较大优化。

    而ArrayBlockingQueue的不用构造节点,加锁和解锁的时间可能占比较大。

   转成双锁之后,对比原来的存取操作,需要多竞争两次。一次是Atomic变量的cas操作,另一次是获得另一把锁的通知操作。可能这部分的损耗,已经比并发存取带来收益更大。

Q:那你怎么证明你上述的观点是正确的呢

A:。。。周一去公司自己实现一个,然后测试一下。

好,周一再见- -。

    原文作者:JUC
    原文地址: https://blog.csdn.net/qq_27007251/article/details/75207050
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞