一、乐观锁VS悲观锁
1)关于悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,Java中synchronized和ReentrantLock以及Read-write locks等就是悲观锁思想的实现。
2)关于乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现,StampedLock就是一种乐观锁
二、CAS
CAS和乐观锁相辅相成
很好理解,比较和交换
英文名compare and swap的缩写,
如果用C语言来表示的时候很简单
int cas(long *addr, long old, long new)
{
/* Executes atomically. */
if(*addr != old)
return 0;
*addr = new;
return 1;
}
但是这种比较和替换会有ABA问题
三、ABA问题
- 进程P1读取了一个数值A。
- P1被挂起(时间片耗尽、中断等),进程P2开始执行
- P2修改数值A为数值B,然后又修改回A
- P1被唤醒,比较后发现数值A没有变化,程序继续执行。
对于P1来说,数值A未发生过改变,但实际上A已经被变化过了,继续使用可能会出现问题
四、ABA问题解决
利用版本号比较可以有效解决ABA问题。
相当于加条件判断
java解决用的是AtomicStampedReference
相当于加了版本戳记