ConcurrentLinkedQueue & CopyOnWriteArrayList

  • ConcurrentLinkedQueue支持高并发读写队列
    实现方式是利用无锁操作
    关键代码
 public boolean offer(E e) {
        checkNotNull(e);
        //创建入队节点
        final Node<E> newNode = new Node<E>(e);
        //t为tail节点,p为尾节点,默认相等,采用失败即重试的方式,直到入队成功
        for (Node<E> t = tail, p = t;;) {
            //获得p的下一个节点
            Node<E> q = p.next;
            // 如果下一个节点是null,也就是p节点就是尾节点
            if (q == null) {
              //将入队节点newNode设置为当前队列尾节点p的next节点
                if (p.casNext(null, newNode)) { 
                   //判断tail节点是不是尾节点,也可以理解为如果插入结点后tail节点和p节点距离达到两个结点
                    if (p != t) 
                     //如果tail不是尾节点则将入队节点设置为tail。
                     // 如果失败了,那么说明有其他线程已经把tail移动过 
                        casTail(t, newNode);  
                    return true;
                }
            }
                 // 如果p节点等于p的next节点,则说明p节点和q节点都为空,表示队列刚初始化,所以返回                            head节点
            else if (p == q)
                p = (t != (t = tail)) ? t : head;
            else
                //p有next节点,表示p的next节点是尾节点,则需要重新更新p后将它指向next节点
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

在如队列的时候利用无所操作控制插入队列操作的原子性
插入过程如图
image

  • CopyOnWriteArrayList是高效的可读可写容器,利用不变性设计模式,将array定义为final类型,只能被替换,不能被更改

关键属性

private volatile transient Object[] array;//底层数据结构

    /**
     * 获取array
     */
    final Object[] getArray() {
        return array;
    }

    /**
     * 设置Object[]
     */
    final void setArray(Object[] a) {
        array = a;
    }

    /**
     * 创建一个CopyOnWriteArrayList
     * 注意:创建了一个0个元素的数组
     */
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }

list.add()操作利用锁控制原子性

/**
     * 在数组末尾添加元素
     * 1)获取锁
     * 2)上锁
     * 3)获取旧数组及其长度
     * 4)创建新数组,容量为旧数组长度+1,将旧数组拷贝到新数组
     * 5)将要增加的元素加入到新数组的末尾,设置全局array为新数组
     */
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;//这里为什么不直接用this.lock(即类中已经初始化好的锁)去上锁
        lock.lock();//上锁
        try {
            Object[] elements = getArray();//获取当前的数组
            int len = elements.length;//获取当前数组元素
            /*
             * Arrays.copyOf(elements, len + 1)的大致执行流程:
             * 1)创建新数组,容量为len+1,
             * 2)将旧数组elements拷贝到新数组,
             * 3)返回新数组
             */
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;//新数组的末尾元素设成e
            setArray(newElements);//设置全局array为新数组
            return true;
        } finally {
            lock.unlock();//解锁
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值