CAS算法

1.为什么使用CAS

因为大多数的同步操作,超过90%的情况是不会碰到互斥的情况的,即不会碰到需要同步的情况,悲观锁则认为一直需要同步,影响了性能,CAS从硬件和算法层面避免这超过90%的情况。

 

2.什么是CAS

CAS 全称Compare-and-Swap,广义上的讲是CAS重入算法和CAS硬件操作。它采用乐观锁的方式,即认为不需要加锁,如果有多线程在同一时间段对同一个变量或者引用的指针进行操作,CAS的原理是,不加锁,本地变量value_0,先保存变量value_0的副本value_0_copy到栈空间,然后申明一个期望值value_update,利用硬件的CAS指令支持(如果不支持,则采用CAS重入算法,原理同上一句的操作),比较新老值value_0_copy和value_0,如果发现老值和新获得的值做比较,如果变化了,说明别的线程对这个值有改变,则认为更新失败,返回,至于返回失败之后是否需要重新执行,需要使用者进行判断,例如ConcurrentLinkedQueue,如果更新失败,ConcurrentLinkedQueue会一直重试,直到成功,但是会存在ABA的问题,如果ABA问题不影响逻辑,对结果没有副作用,则不需要考虑,如果对结果有副作用,则需要考虑使用其它方式。

ConcurrentLinkedQueue offer的源码

    public boolean offer(E e) {
        final Node<E> newNode = newNode(Objects.requireNonNull(e));

        for (Node<E> t = tail, p = t;;) {
            Node<E> q = p.next;
            if (q == null) {
                // p is last node 这里,如果p的next是null,
                //说明p是最后一个,即为尾部tail,如果不是,重入外面的循环
                if (casNext(p, null, newNode)) {
                    // Successful CAS is the linearization point
                    // for e to become an element of this queue,
                    // and for newNode to become "live".
                    //因为p节点已经更新,t也需要更新,因为t正在指向更新前的节点,
                    //不过这里更新失败也无所谓,因为casNext已经成功添加了新的尾部节点,
                    //但是这里的目的我可能没理解透?
                    //是设计者太严谨了,不放过任何一个地方,
                    //即使本地的栈空间不需要的变量也要保证严谨?
                    if (p != t) // hop two nodes at a time
                        casTail(t, newNode);  // Failure is OK.
                    return true;
                }
                // Lost CAS race to another thread; re-read next
            }
            else if (p == q)
                // We have fallen off list.  If tail is unchanged, it
                // will also be off-list, in which case we need to
                // jump to head, from which all live nodes are always
                // reachable.  Else the new tail is a better bet.
                p = (t != (t = tail)) ? t : head;
            else
                // Check for tail updates after two hops.
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
    return U.compareAndSwapObject(node, NEXT, cmp, val);
}

private boolean casTail(Node<E> cmp, Node<E> val) {
    return U.compareAndSwapObject(this, TAIL, cmp, val);
}

 

3.ABA问题的处理

AtomicStampedReference加入时间戳解决ABA问题,1A 2B 3A

 

4.JVM对synchronized锁的优化

经过Java版本不停的改进,之前的synchronized属于完全悲观锁,后面的性能提升主要作了如下优化,优先使用乐观锁,锁的信息动态改变当前锁的状态,主要记录了如下3种状态,0,1,2,乐观锁,轻量锁和重量锁,一般情况下,使用乐观锁,如果碰到需要同步的情况,+1,知道变化成重量锁的方式,当然,使用重量锁是一直最不理想的状态,说明真的有许多并发的情况需要处理,这可能出现在高并发的服务器,这就不是开头说道的90%的情况下都不需要同步。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值