Java并发2——CAS

Posted 我永远信仰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java并发2——CAS相关的知识,希望对你有一定的参考价值。

CAS、乐观锁、悲观锁

线程同步操作资源对象

多个线程想要操作一个资源对象。如何实现同步?

第一反应是使用互斥锁、但是互斥锁同步方式是悲观的。

悲观锁

悲观锁:操作系统认为,如果不严格同步线程调用,那么一定会产生异常。

缺点:如果大部分线程只是对资源进行读操作,悲观锁在每次被调用都是对资源经行锁定,效率无疑是极低的。

或者在同步代码块执行的时间远远小于线程切换的时间,使用悲观锁也是非常不好的。

那么如何实现:不锁定资源,也能线程同步?

那就是CAS:(Compare and swap)比较并且交换。

乐观锁(CAS)

比如两个线程争一个资源对象,资源对象中有一个状态值,0表示空闲没有被线程使用,那么这时候线程可以去获取该资源对象。

当线程拿到该资源对象,会生成两个值oldValue=0,newValue=1;oldValue表示拿到资源对象时候资源对象的值,这是作用于compare;newValue表示线程将其修改的值。

假设此时A、B两个线程都抢到了资源对象,想修改它的状态值为1,并占用它。如果A线程执行的比较好。先将资源对象的状态值swap操作修改成1,那么当B线程修改的时候发现oldValue不等于资源对象的状态值,因为其被A修改了,所以放弃swap操作。

不过B也不是直接放弃,而是进行自旋等待A的释放,不断的对资源对象经行compare,通常会配置自旋次数来防止死循环,因为自选是cpu空转,占用一定的开销,特别是自选线程很多的情况,这个后面总结。

但这个情况下,需要保证cas是原子性的。否则出现ABA问题。

那么应该如何实现cas的原子性呢?通过锁来实现?那前面的功夫岂不是白搭了

这个不用我们担心,CPU已经原生的支持了cas,上层经行调用即可。

底层的cmpxchg,留个坑,底层是如何实现无锁同步的

CAS这种同步机制,被称为乐观锁。CAS没有用到锁,是一种无锁的同步机制。

乐观锁不用上锁,而是cpu将这个过程变成是字节码指令级别的,拥有原子性。如果乐观锁再加锁,就违背了无锁的初衷

Java中的例子

启动三条线程,将一个值累加到1000.

public class Test01 {
    static AtomicInteger num = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (num.get() < 1000) {
                        System.out.println(Thread.currentThread().getName() + ":" + num.incrementAndGet());
                    }
                }
            }).start();
        }
    }
}

AtomicInteger的底层是如何通过CAS做到无锁同步

查看AtomicInteger源码

看我们调用的num.incrementAndGet()方法,确实是这样

查看getAndAddInt,这里调用了CAS,而且这里出现了一个循环,也就是之前说到的自旋。循环次数是可以通过启动参数来配置,如果不配置,默认次数是10,并不会出现死循环。

CAS是一个本地方法,和调用的平台相关

ABA

[CAS是什么?ABA问题又应该如何理解? - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/139635112#:~:text=ABA 问题的过程是当有两个线程 T1 和 T2 从内存中获取到值A,线程 T2 通过某些操作把内存,值修改为B,然后又经过某些操作将值修改为回值A,T2退出。 线程 T1 进行操作的时候 ,使用预期值同内存中的值比较,此时均为A,修改成功退出。 但是此时的A以及不是原先的A了,这就是 ABA 问题)

以上是关于Java并发2——CAS的主要内容,如果未能解决你的问题,请参考以下文章

Java并发2——CAS

Java多线程和并发,CAS(Compare and Swap)

Java并发编程之CAS

Java——多线程高并发系列之理解CAS原子变量类的使用

Java——多线程高并发系列之理解CAS原子变量类的使用

Java并发编程系列- 原子操作与CAS