CAS的ABA问题

一、CAS概念

1. 悲观锁:一个线程加锁后其他线程会挂起,直到持有锁的线程释放锁,悲观锁从最坏的情况考虑问题。独占锁是一种悲观锁,例如synchronized关键字加锁,例如可重入锁ReentrantLock

2. 乐观锁:不加锁,多个线程共同执行,如果发生了冲突,就去重试(do...while...),乐观锁从最好的情况考虑问题

3. 悲观锁和乐观锁哪个效率高,要看具体情况

4. CAS(Compare And Swap,比较并交换)算法是一种乐观锁

5. CAS有3个操作数:旧值A,新值B,内存里的值V

6. CAS算法:当旧值A和内存里的值V相同时,把V修改为新值B并返回true;否则返回false,再次进行CAS操作

7. java.util.concurrent包下的类进行原子操作,底层使用CAS乐观算法,CAS使用底层的unsafe方法;例如AutomaticInteger类

8. unsafe方法:Java无法访问底层系统,需要通过本地native方法进行访问,UnSafe类相当于一个后门,可以像指针一样访问特定内存的数据

9. CAS失败会重试,所以CPU消耗比较大

二、ABA问题

1. 当一个线程进行CAS操作时,内存值value为A

2. 其他线程把内存值先修改为B,再修改为A,内存值的变化即A->B->A

3. 当前线程认为value没有变化,继续进行操作

4. ABA可能会引发问题,比如修改了其他值,但是当前线程不知道;也可能不会,根据业务逻辑判断

三、解决ABA问题

1. 再加一个变量flag,如果修改了内存值value,每次变化时对flag加1

2. 使用版本戳version

3. AutomaticMarkableReference<V>

4. AutomaticStampedReference<V>

参考:

https://blog.csdn.net/justry_deng/article/details/83449038

https://blog.csdn.net/xiaobudian0381/article/details/91564648