悲观锁:
每次拿数据都会加锁,Synchronized属于悲观锁[一段执行逻辑加上悲观锁,不同线程同时执行时,只能有一个线程执行,其他的线程在入口处等待,直到锁被释放]
乐观锁:
一段执行逻辑加上乐观锁,不同线程同时执行时,可以同时进入执行,在最后更新数据的时候要检查这些数据是否被其他线程修改了(版本和执行初是否相同),没有修改则进行更新,否则放弃本次操作
核心算法:CAS算法
内存值、预期值、新值(首先检查某块内存的值是否跟之前我读取时的一样,如不一样则表示期间此内存值已经被别的线程更改过,舍弃本次操作,否则说明期间没有其他线程对此内存值操作,可以把新值设置给此块内存)
如何保证CAS中的原子性:由CPU硬件指令实现[getAndIncrement中compareAndSet]
1 public class AtomicInt { 2 private volatile int value; 3 public final int get() { 4 return value; 5 } 6 7 publicfinal int getAndIncrement() { 8 for (;;) { 9 int current = get(); 10 int next = current + 1; 11 if (compareAndSet(current, next)) 12 return current; 13 } 14 } 15 16 public final boolean compareAndSet(int expect, int update) { 17 //Unsafe类提供的硬件级别的compareAndSwapInt方法; 18 } 19 }
CAS存在ABA问题:假如内存值原来是A,后来被一条线程改为B,最后又被改成了A,则CAS认为此内存值并没有发生改变,但实际上是有被其他线程改过的
解决方法:解决的思路是引入版本号,每次变量更新都把版本号加一
在JDK18中进行了增强[unsafe.getAndAddInt]
public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); }