深度分析ConcurrentLinkedQueue原理


title: 深度分析ConcurrentLinkedQueue原理
date: 2019-04-23 20:19:04
categories:

  • Java并发
    tags:
  • 并发容器

引言

JUC包中提供了许多线程安全的并发容器,使用这些容器,无需我们再去手动的设置锁,就能实现线程安全。在这些并发容器中,又分为阻塞与非阻塞(简单来说线程进行元素的放置与取出操作时,可以将线程阻塞)。ConcurrentLinkedQueue就是以非阻塞方式来实现的,这个并发容器类通过循环CAS操作来实现线程安全队列,它不会导致当前线程被暂停,因此也避免了线程上下文切换的开销。

CAS的原理

CAS(Compare and Swap):比较并交换。它是对一种处理器指令的称呼,在Java中,CAS通过调用JNI的代码实现的。CAS操作顾名思义,先比较再交换(或者说更新),通过一段伪代码来看:

for(;;){
   
    ...
     public boolean cas(V a, V b ,V c){
   
        //a为想要修改的变量,b为当前线程调用CAS操作时a的值(即a的旧值),c为新值

        if(b == a){
    //检查其他线程是否已经对a进行了修改
            b = c; //更新
            return true; //更新成功
        }

        return false; //更新操作
    }  
    ...
}

当某个线程要执行CAS操作时,如果想要修改的值与调用CAS操作的线程所提供的旧值相同时,说明其他线程并未对其进行修改,则这个线程可以对其进行修改。而其他的线程则更新失败,然后继续进行尝试,直至成功。

ConcurrentLinkedQueue原理

简单来说,ConcurrentLinkedQueue就相当于LinkedList的线程安全版,即是一个单向链表,在其内部有个私有静态类Node<E>,通过这个类,将元素封装在其中,并保存下一个节点(next),Node<E>内部通过一个UNSAFE类来完成CAS操作。

Node类的主要代码:

private static class Node<E> {
   
        volatile E item; // volatile声明
        volatile Node<E> next; // volatile声明
        // 构造方法  在地址itemOffset处, 值替换为item
        Node(E item) {
   
            UNSAFE.putObject(this, itemOffset, item);
        }
        // CAS操作:比较并交换,原子的更改itemOffset地址的变量。如果变量的值为cmp,并成功替换为val 返回true  
        boolean casItem(E cmp, E val) {
   
            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
        }
       // 将nextOffset地址的值替换为x
        void lazySetNext(Node<E> val) 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值