浅谈CAS


一、什么是CAS?

CAS全名是Compare And Swap(比较与替换),它是用来解决高并发问题的一种方案。实现的原理大致上就是先将需要修改的变量V读取到变量E中缓存起来,然后在写入新变量U的时候将E和重新读取出来的V变量比较一遍,如果两者一致则把U写入V中,不一致则表明期间有其它线程修改了属性,然后进行自旋重新走一遍流程,直到修改操作执行完成。
可以将CAS看作是(数据库)乐观锁的一种简化实现版本

二、CAS的优缺点

优点:

  • 它是一个无锁操作,所以在并发量不是很高的情况下可以极大的减小加锁带来的时间消耗

缺点:

  • 它无法解决ABA问题,就是在修改期间有线程将之改变后又改回去的情况下,它是没有办法做出判断并记录操作的。这对一些流水记录操作业务的情景不太友好;
  • 由于CAS是通过自旋实现的,所以如果多次更新不成功,那么其他线程不停的执行读取操作所造成的性能开销比较大;
  • CAS只能保证一个变量的原子性操作,不能保证代码块的原子性;

三、CAS的简单实现

CAS在jdk中有自己的实现,它主要是在Unsafe这个类中,下面有一段简单实现代码:

工具类:

package com.muyichen.demo.cas;

import lombok.Data;
import org.springframework.objenesis.instantiator.util.UnsafeUtils;
import sun.misc.Unsafe;

@Data
public class CASLock {

    private volatile int state;

    private static Unsafe unsafe;

    private static Long offSet;

    static {
        unsafe = UnsafeUtils.getUnsafe();
        try {
            offSet = unsafe.objectFieldOffset(CASLock.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    public boolean cas() {
        return unsafe.compareAndSwapInt(this, offSet, 0, 1);
    }

}

测试类:

package com.muyichen.demo.cas;

import org.springframework.objenesis.instantiator.util.UnsafeUtils;
import sun.misc.Unsafe;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

public class CASTest {

    private volatile static int sum = 0;

    /**
     * 直接使用原子类进行操作
     */
    private static AtomicInteger sums = new AtomicInteger();

    /**
     * 使用synchronized加锁
     */
    static Object object = "";

    /**
     * 使用Lock加锁
     */
    static ReentrantLock lock = new ReentrantLock();

    /**
     * 使用CAS
     */
    static CASLock casLock = new CASLock();


    public static void main(String[] args) throws InterruptedException {

//        Entity entity = new Entity();
//
//        Unsafe unsafe = UnsafeUtils.getUnsafe();
//
//        // 12表示偏移量:8位对象头+4位压缩指针;0表示对比值,1表示修改值
//        unsafe.compareAndSwapInt(entity, 12, 0, 1);
//        System.out.println(entity.getX());
//
//        unsafe.compareAndSwapInt(entity, 12, 1, 3);
//        System.out.println(entity.getX());
//
//        unsafe.compareAndSwapInt(entity, 12, 1, 5);
//        // 这次修改由于x的值已经是3了,所以修改不成功
//        System.out.println(entity.getX());

        long millis = System.currentTimeMillis();
        CountDownLatch latch = new CountDownLatch(10);

//        for (int i = 0; i < 10; i++) {
//            Thread thread = new Thread(() -> {
//                synchronized (object) {
//                    for (int j = 0; j < 10000; j++) {
//                        sum++;
//                    }
//                    latch.countDown();
//                }
//            });
//            thread.start();
//        }

//        for (int i = 0; i < 10; i++) {
//            Thread thread = new Thread(() -> {
//                lock.lock();
//                try {
//                    for (int j = 0; j < 10000; j++) {
//                        sum++;
//                    }
//                } finally {
//                    lock.unlock();
//                    latch.countDown();
//                }
//            });
//            thread.start();
//        }

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                for (;;) {
                    if (casLock.getState() == 0&&casLock.cas()) {
                        for (int j = 0; j < 10000; j++) {
                            sum++;
                        }
                        casLock.setState(0);
                        latch.countDown();
                        break;
                    }
                }
            });
            thread.start();
        }

        latch.await();

        System.out.println("执行耗时:" + (System.currentTimeMillis() - millis));
        System.out.println(sum);
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

缘丶沐逸尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值