Java CAS 比较并交换

Java CAS 比较并交换

概述

  • Java CAS(Compare-and-Swap)是一种无锁算法,它基于比较和交换的思想来实现多线程之间的变量同步。目的为了防止变量在使用过程中被其他线程所修改。

  • CAS操作包含三个操作数:内存值(V)、预期原值(A)和新值(B)。

    • 如果内存值等于预期原值时,将新值赋值给内存值。
    • 否则,不做操作。
  • CAS操作的实现原理是利用CPU提供的原子操作指令,通过硬件保证了比较-更新操作的原子性 。

  • CAS问题:

    • ABA问题:假如一个值原来是A,现在变为B,再后来变为A,那么CAS检查时会发现它的值没有发生变化,但是实际已经发生变化了。

      ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加1,那么A→B→A就会变成1A→2B→3A。也可以使用Java提供的原子类AtomicMarkableReference、AtomicStampedReference。

    • 自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。默认自旋10次。

    • 当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁。

  • 原子类:

    • 更新基本类型类:AtomicBoolean,AtomicInteger,AtomicLong
    • 更新数组类:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
    • 更新引用类型:AtomicReference,AtomicMarkableReference,AtomicStampedReference

在这里插入图片描述

线程干扰问题

public class Demo {

    public static int i = 0;

    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("内存值:" + i);
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i = i + 1;
                System.out.println("新值:" + i);
            }
        };
        thread.start();
        try {
            Thread.sleep(50L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //干扰
        i = 5;
    }
}

输出:

内存值:0
新值:6

说明:预期值是1,最终返回值是6,这是因为受到其他线程的干扰,值在被篡改了。

使用CAS技术解决问题

public class Demo {

    public static int i = 0;

    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                int oldValue = i;
                System.out.println("内存值:" + oldValue);
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                boolean result = compareAndSwap(i, oldValue, i + 1);
                System.out.println("设置是否成功:" + result);
                System.out.println("新值:" + i);
            }
        };
        thread.start();
        try {
            Thread.sleep(50L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        i = 5;
    }

    /**
     * 比较并交换
     *
     * @param oldValue      内存值
     * @param expectedValue 预期原值
     * @param newValue      新值
     * @return 				设置成功返回true;否则返回false
     */
    public static boolean compareAndSwap(int oldValue, int expectedValue, int newValue) {
        if (expectedValue == oldValue) {
            i = newValue;
            return true;
        } else {
            return false;
        }
    }
}

输出:

内存值:0
设置是否成功:false
新值:5

说明:CAS就是在做值操作前做一次判断是否被篡改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值