CAS算法学习

11 篇文章 0 订阅

CAS算法学习

概念

CAS就是compareAndSwap的缩写,一句话描述:比较并交换。是一个轻量级的同步机制。

CAS算法涉及到3个操作数:

  • 需要读写的内存值V
  • 进行比较的值A
  • 需要更新的值B
怎么使用

以AtomicInteger类进行说明

public class CASDemo {

    public static void main(String[] args) {
        // 初始值为1
        AtomicInteger atomicInteger = new AtomicInteger(1);
        // 期望值是1,更新值为2,返回true代表更新成功
        System.out.println(atomicInteger.compareAndSet(1, 2));
        // 期望值是1,更新值为3,返回false代表更新失败(最新值已经是2)
        System.out.println(atomicInteger.compareAndSet(1, 3));
    }

}
有什么作用

可以不加锁达到保证数据的原子性,相对于synchronized关键字来说的话,它是轻量级的。

从一个简单的示例来进行说明:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class CASDemo {

    static AtomicInteger atomicInteger = new AtomicInteger(0);

    static volatile int count = 0;

    /**
     * 不需要加锁,就能保证原子性
     */
    public static void addPlusPlusAtomic() {
        atomicInteger.getAndIncrement();
    }

    /**
     * 需要加synchronized+volatile关键字才能保证原子性
     */
    public static synchronized void addPlusPlus() {
        count++;
    }

    public static void main(String[] args) throws InterruptedException {
        int num = 200;
        ExecutorService executor = Executors.newFixedThreadPool(num);

        // 定义200个任务,每个任务执行1000次
        for (int i = 0; i < num; i++) {
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName());
                for (int j = 0; j < 1000; j++) {
                    addPlusPlus();
                    addPlusPlusAtomic();
                }
            });
        }

        executor.shutdown();
        // 等待子线程执行完成
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);
        // 输出计算结果
        System.out.println("atomicInteger="+atomicInteger.get());
        System.out.println("count="+count);
    }

}
底层原理

通过JDK自带的Unsafe类进行实现的,调用的是native方法,从而达到原子性。

这个类可以直接操作物理内存的数据,相当于C语言的一个指针。

CAS是一条CPU的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe提供的CAS方法(如compareAndSwapXXX)底层实现即为CPU指令cmpxchg。

以AtomicInteger类的getAndIncrement()方法进行说明:

	private static final Unsafe unsafe = Unsafe.getUnsafe();
    /**
     * value属性的内存偏移量(内存地址)
     */
    private static final long valueOffset;

    static {
        try {
            // 拿到value属性的内存地址
            valueOffset = unsafe.objectFieldOffset
                    (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    /**
     * 当前值
     */
    private volatile int value;

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

    /**
     * CAS自旋
     * @param var1 当前对象
     * @param var2 value属性的内存偏移量(内存地址)
     * @param var4 1
     * @return
     */
    public final int getAndAddInt(Object var1, long var2, int var4) {
        // 当前value属性的真实值
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)/* 如果期望值与真实值一样,就加一,否则继续循环判断,直到更新成功为止 */);

        return var5;
    }

PS:里面的注释是我自己加的,便于理解。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值