java生产者消费者专题---谈谈优化(四)

 java生产者消费者专题---谈谈优化(三)中使用了一个锁对LinkedList进行锁定,实际可将队头和队尾各用一个锁,这样同时添加与移除元素时不会互相竞争,只有同时添加的线程或者同时移除的线程之间才会互相竞争。核心代码如下:

static class Node<T> {
        T val;
        Node<T> next;

        public Node(T val) {
            super();
            this.val = val;
        }

        public Node(T val, Node<T> next) {
            super();
            this.val = val;
            this.next = next;
        }

    }

    private Node<T> headNode;
    private Node<T> tailNode;

{

headNode =tailNode = new Node<T>(null);

}

现分析队头与队尾节点可以分别采用不同锁的原因:

1、一开始take线程将由于队列为空而进入wait状态,put线程进行正常入队操作即tailNode=tailNode.next=newNode;

2、经过第一步后队列中有1个有效元素,且头节点指向一开始的哑节点,哑节点指向newNode,同时尾节点也指向newNode;

3、此时take线程被激活,与put线程同时处于活动状态,并假设此时只有一个take线程和一个put线程,它们会同时运行;

4、先说明take一个节点的步骤,由于头节点指向哑节点,因此哑节点指向的第一个节点是真正的数据节点,在得到数据节点的数据后,会将数据节点的数据域置空并将头节点指向它(此时该数据节点已经充当了新的哑节点角色,原先的哑巴节点会被废弃,具体可以看下LinkedBlockingQueue的源代码)。

5、通过第四步可以看出take时不会对数据节点的next域产生影响,而put时仅仅对最后一个数据节点的next域产生影响,所以head节点和tail节点可以采用不同的锁,即take线程和put线程是永远不会发生竞争的!

哑节点的设计是实现该方法的核心部分,源码大家就参考LinkedBlockingQueue即可,下篇将分析与ArrayBlockingQueue的效率差异!

 

转载于:https://my.oschina.net/u/1268334/blog/3059690

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值