Java CAS

一、CAS是什么?

CAS是compare and swap的简称,从字面上理解就是比较并更新,这是一个实现并发算法时常用到的一种技术。简单来说:从某一个内存上取V,和预期值A进行比较,如果内存V和预期值A的结果相等,那么我们就把新值B更新到内存,如果不相等,那么就重复上述操作直到成功为止。这是一种实现并发算法时常用到的技术,是乐观锁(与之相对synchronized是一种悲观锁)。

二、原理

CAS操作需要有三个操作数:内存地址V,旧的预期值A,即将要更新的目标值B

CAS指令执行时,当且仅当内存地址V的值与预期值A相等时,将内存地址V的值修改为B,否则就什么都不做。整个比较并替换的操作是一个原子操作。

三、具体实现方式

Java中的Atomic系列就是使用CAS实现的,以下就以AtomicInteger为例来看下Java的实现过程:

3.1 属性

private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //内存偏移地址
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
	
	//变量用volatile修饰
    private volatile int value;

3.2 自增

对当前的值自增1

    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

这里调用了Unsafe的一个方法,实现如下:

public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

这里又调用了本类的compareAndSwapInt方法:

 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

这个方法利用CAS操作,将var4和内存偏移到的变量进行对比,如果相等,那么将这个地址所代表的变量设置为var5,否则返回false

四、CAS优点和缺点

4.1 缺点

4.1.1 ABA问题

假如线程1从内存X中取出A,这时候另一线程2也从X中取出A,并且线程2进行了一些操作将内存X中的值变成了B,然后线程2又将内存X中的数据变成A,这时候线程1进行CAS操作发现内存X中仍然是A,然后线程1操作成功。虽然线程1的CAS操作成功,但是整个过程是有问题的。比如链表的头在变化了两次后恢复了原值,但是不代表链表没有发生变化。

所以JAVA中提供了AtomicStampedReference/AtomicMarkableReference来处理会发生ABA问题的场景,主要是在对象中额外再增加一个标记来标识对象是否有过变更。

4.1.2 循环时间开销很大

CAS通常是配合无限循环一起使用的,如果CAS失败,会一直进行尝试。如果CAS长时间一直不成功,可能会给CPU带来很大的开销。

4.1.3 只能保证一个变量的原子操作

当对一个变量进行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个变量进行操作时,CAS目前无法直接保证操作的原子性。但是我们可以通过以下两种方式来解决:

  • 使用互斥锁来保证原子性
  • 将多个变量封装成对象,通过AtomicReference来保证原子性。

4.2 优点

和Synchronized相比,省去了挂起线程、恢复线程的开销,资源耗费少

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值