首页 > 其他 > 详细

017 无锁与CAS

时间:2018-05-06 01:16:27      阅读:315      评论:0      收藏:0      [点我收藏+]

一 . 概述

我们知道加锁会对多线程的并发有影响,那么我们是否有无锁的方式保证线程的安全性呢?有的,就是CAS方式.

  CAS的核心就是乐观的尝试,将线程的阻塞变成了线程的尝试,认为即使在不断尝试的代价也比阻塞后唤醒的代价要小.


 

二 CAS

CAS到底是什么呢? 其实就是一个JVM的指令,其中这个指令的执行是原子性的,也就是说不会被打断.

  我们看下AtomicInter的原子实现:  

    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

我们看到使用了unsafe完成了CAS操作,CAS代表的就是比较并且更新(交换).

    当现在的值等于期待值就会更新并且返回ture,

    不等于就会返回false,并且不会更新.

    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }

我们看上述的JDK的实现,使用了一个while循环不断试探是否是线程安全的.

  我们知道while体内的操作可能不是安全的,也就是会发生修改修改,那么现在的值就和期待值不一致,那么CAS保证不去更新.

  循环就会再次尝试,知道成功为止.

  通过这种尝试的方式保证操作是线程安全的.


 

三 .ABA问题

我们知道,CAS不保证循环体的过程,但是保证结果是正确的,这也就是说循环体内

  可能发生了一个自减操作,然后又做出了一个自增操作,这种情况下,期待值和实际值确实是一致的,但是不能保证原子性了.

问题解决:

  解决的方式很简单,我们在原始的CAS之上加上一个时间戳,时间戳可以保证两次操作之间不应该有其它的操作.

  为此,出现了AtomicStampedReference这样的类可以保证线程安全.

017 无锁与CAS

原文:https://www.cnblogs.com/trekxu/p/8996782.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!