浅谈CAS原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yu280265067/article/details/50824881
    java并发编程也研究了一段时间了,对CAS的原理总是不太理解,今天再研究了一下,记录一些自己的理解。
    说到CAS,再java中的某些情况下,甚至jdk1.5以后的大多数情况,并发编程都是用CAS实现的,那么CAS到底如何能够实现锁的功能呢?
    拿a++操作举例
public final int getAndIncrement() {  
    for (;;) {  
        int current = get();  
        int next = current + 1;  
        if (compareAndSet(current, next))  
            return current;  
    }  
}   

这里面的compareAndSet的功能为,a与current比较,如果相等则把a的值变为next;这时候可以保证在int next = current + 1;与if();之间不会被其他线程抢占(因为a的值在这段时间内没有变),如果被抢占则会做自旋操作。这就在某种程度上可以实现原子性操作。

这是一种不加锁而实现操作原子化的一种巧妙的编程方式,不仅在java的jvm种,甚至在操作系统的底层并发实现机制中也有CAS的大量应用。

但是这种方式有没有缺点呢?

当然也会有:
1、ABA问题

CAS操作容易导致ABA问题,也就是在做a++之间,a可能被多个线程修改过了,只不过回到了最初的值,这时CAS会认为a的值没有变。a在外面 逛了一圈回来,你能保证它没有做任何坏事,不能!!也许它讨闲,把b的值减了一下,把c的值加了一下等等,更有甚者如果a是一个对象,这个对象有可能是新 创建出来的,a是一个引用呢情况又如何,所以这里面还是存在着很多问题的,解决ABA问题的方法有很多,可以考虑增加一个修改计数,只有修改计数不变的且 a值不变的情况下才做a++,也可以考虑引入版本号,当版本号相同时才做a++操作等,这和事务原子性处理有点类似!


2、比较花费CPU资源,即使没有任何争用也会做一些无用功。

3、会增加程序测试的复杂度,稍不注意就会出现问题。

总结

可以用CAS在无锁的情况下实现原子操作,但要明确应用场合,非常简单的操作且又不想引入锁可以考虑使用CAS操作,当想要非阻塞地完成某一操作也可以考虑CAS。不推荐在复杂操作中引入CAS,会使程序可读性变差,且难以测试,同时会出现ABA问题。

猜你喜欢

转载自blog.csdn.net/yu280265067/article/details/50824881