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