CAS . . . .

文章详细介绍了CAS(CompareandSwap)机制在多线程中的作用,包括其原子类如AtomicInteger的使用,以及如何通过UnSafe类实现CAS操作。同时,讨论了CAS的底层原理,指出其可能导致的循环开销大和ABA问题,并通过示例展示了如何使用AtomicStampedReference解决ABA问题。此外,文章还探讨了自旋锁的概念并提供了一个简单的自旋锁实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、原子类

java.util.concurrent.atomic 

二、没有CAS之前



三、使用CAS之后



四、CAS是什么?

1. 说明与原理



2.硬件基本保证

3.源码分析compareAndSet(int expect, int update)

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

五、CAS底层原理?如何知道,谈谈你对UnSafe的理解

1.UnSafe


2.我们知道i++线程不安全的,那atomicInteger.getAndIncrement()

在这里插入图片描述

3.源码分析

在这里插入图片描述


六、原子引用



七、CAS与自旋锁,借鉴CAS思想

1.自旋锁是什么


2.自己实现一个自旋锁SpinLockDemo

/**
 * 题目:实现一个自旋锁,复习CAS思想
 * 自旋锁好处:循环比较获取没有类似wait的阻塞
 * 
 * 通过CAS操作完成自旋锁,A线程先进来调用lock方法,自己持有5秒钟,B随后进来发现
 * 当前线程持有锁,所以只能通过自旋等待,知道A释放锁后B随后抢到。
 * 
 */
public class SpinLockDemo {

    AtomicReference<Thread>  atomicReference=new AtomicReference<>();

    public static void main(String[] args) {
        SpinLockDemo spinLockDemo = new SpinLockDemo();
        new Thread(()->{
            spinLockDemo.lock();
            try { TimeUnit.SECONDS.sleep(5); }catch (Exception e){e.getMessage();}
            spinLockDemo.unLock();
        },"A").start();

        try { TimeUnit.SECONDS.sleep(1); }catch (Exception e){e.getMessage();}
        new Thread(()->{
            spinLockDemo.lock();
            spinLockDemo.unLock();
        },"B").start();
    }

    public void lock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+" ---come in");
        while (!atomicReference.compareAndSet(null,thread)){

        }
    }

    public void unLock(){
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread,null);
        System.out.println(Thread.currentThread().getName()+" ---task over,unLock...");
    }

}


八、CAS缺点

1.循环时间长开销很大

2.ABA问题: 比较+版本号一起上

①ABA问题怎么产生的

②:版本号时间戳原子引用

AtomicStampedReference简单case

public class AtomicStampedDemo {
    public static void main(String[] args) {
        Book javaBook = new Book(1, "Java");
        AtomicStampedReference<Book> stampedReference=new AtomicStampedReference<>(javaBook,1);

        System.out.println(stampedReference.getReference()+" "+stampedReference.getStamp());
        Book mysqlBook = new Book(2, "MySql");

        boolean b;
        b= stampedReference.compareAndSet(javaBook, mysqlBook, stampedReference.getStamp(), stampedReference.getStamp()+1);
        System.out.println(b+" "+stampedReference.getReference()+ " "+stampedReference.getStamp());

        b= stampedReference.compareAndSet(mysqlBook, javaBook, stampedReference.getStamp(), stampedReference.getStamp()+1);
        System.out.println(b+" "+stampedReference.getReference()+ " "+stampedReference.getStamp());
    }
}


ABADemo

public class ABADemo {
    static AtomicInteger atomicInteger=new AtomicInteger(100);
    public static void main(String[] args) {
        new Thread(()->{
            atomicInteger.compareAndSet(100,101);
            atomicInteger.compareAndSet(101,100);
        },"t1").start();

        try { TimeUnit.SECONDS.sleep(1); }catch (Exception e){e.getMessage();}

        new Thread(()->{
            boolean b = atomicInteger.compareAndSet(100, 2023);
            System.out.println(b +" "+ atomicInteger.get());
        },"t1").start();

    }
}
true 2023


public class ABADemo {
    static AtomicInteger atomicInteger=new AtomicInteger(100);
    static AtomicStampedReference<Integer> stampedReference=new AtomicStampedReference(100,1);
    public static void main(String[] args) {
        new Thread(()->{
            int stamp = stampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+" 首次版本号 "+stamp);
            //等待1秒 保证t2线程获取到和我一样的版本号
            try { TimeUnit.SECONDS.sleep(1); }catch (Exception e){e.getMessage();}
            stampedReference.compareAndSet(100,101,stampedReference.getStamp(),stampedReference.getStamp()+1);
            stampedReference.compareAndSet(101,100,stampedReference.getStamp(),stampedReference.getStamp()+1);
        },"t1").start();
        
        new Thread(()->{
            int stamp = stampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+" 首次版本号 "+stamp);
            //等待2秒 保证t1线程发声ABA问题
            try { TimeUnit.SECONDS.sleep(2); }catch (Exception e){e.getMessage();}
            boolean b = stampedReference.compareAndSet(100, 2023,stamp,stampedReference.getStamp()+1);
            System.out.println(b +" "+ stampedReference.getReference() + " "+stampedReference.getStamp());
        },"t2").start();

    }
}
t1 首次版本号 1
t2 首次版本号 1
false 100 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值