悲观锁: 悲观的认为别人会修改我访问的数据, 所以会将资源锁定起来, 自己用完了再释放资源. 使用 synchronized 锁住代码块就是一个悲观锁的体现, 逻辑不严谨会出现死锁.
乐观锁: 乐观的认为别人不会修改数据. 会引深出ABA问题. 解决方案是加入version 版本号和 cas 算法.
public class ABATest {
/**
* 存在ABA 问题
* @param args
*/
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(1);
new Thread(()->{
int value = atomicInteger.get();
System.out.println("thread 1 read value: " + value);
// 阻塞1s
LockSupport.parkNanos(1000000000L);
if (atomicInteger.compareAndSet(value, 3)) {
System.out.println("thread 1 update from " + value + " to 3");
} else {
System.out.println("thread 1 update fail!");
}
}).start();
new Thread(()->{
int value = atomicInteger.get();
System.out.println("thread 2 read value: " + value);
if (atomicInteger.compareAndSet(value, 2)) {
System.out.println("thread 2 update from " + value + " to 2");
// do sth
value = atomicInteger.get();
System.out.println("thread 2 read value: " + value);
if (atomicInteger.compareAndSet(value, 1)) {
System.out.println("thread 2 update from " + value + " to 1");
}
}
}).start();
}
}
public class ABAHandle {
public static void main(String[] args) {
abaHandler();
}
private static void abaHandler() {
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1, 1);
new Thread(()->{
int[] stampHolder = new int[1];
int value = atomicStampedReference.get(stampHolder);
int stamp = stampHolder[0];
System.out.println("thread 1 read value: " + value + ", stamp: " + stamp);
// 阻塞1s
LockSupport.parkNanos(1000000000L);
if (atomicStampedReference.compareAndSet(value, 3, stamp, stamp + 1)) {
System.out.println("thread 1 update from " + value + " to 3");
} else {
System.out.println("thread 1 update fail!");
}
}).start();
new Thread(()->{
int[] stampHolder = new int[1];
int value = atomicStampedReference.get(stampHolder);
int stamp = stampHolder[0];
System.out.println("thread 2 read value: " + value + ", stamp: " + stamp);
if (atomicStampedReference.compareAndSet(value, 2, stamp, stamp + 1)) {
System.out.println("thread 2 update from " + value + " to 2");
// do sth
value = atomicStampedReference.get(stampHolder);
stamp = stampHolder[0];
System.out.println("thread 2 read value: " + value + ", stamp: " + stamp);
if (atomicStampedReference.compareAndSet(value, 1, stamp, stamp + 1)) {
System.out.println("thread 2 update from " + value + " to 1");
}
}
}).start();
}
}