原子引用
ABA问题
一个线程 CAS操作的时候cas(1,2) 另一个线程 比他快 也执行了 CAS操作cas(1,3) cas(3,1) 值已经被修改了
public class CASDemo {
//CAS compareAndSet 比较并交换!
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// public final boolean compareAndSet(int expect, int update)
//如果我们期望的值达到了 那么就更新,否则就不更新
// ========捣乱的线程==========
atomicInteger.compareAndSet(2020,2021);
System.out.println(atomicInteger.get());
atomicInteger.compareAndSet(2021,2020);
System.out.println(atomicInteger.get());
// ========捣乱的线程==========
atomicInteger.compareAndSet(2020,6666);
System.out.println(atomicInteger.get());
}
}
解决ABA问题 引入原子引用 对应的思想:乐观锁
AtmoicReference
带版本号的原子操作
Integer使用了对象缓存机制,默认范围是-128 ~ 127,推荐使用静态工厂方法valueOf获取对象实例,而不是new 因为valueOf使用缓存,而new一定会创建新的对象分配新的内存空间
public class CASDemo {
//CAS compareAndSet 比较并交换!
public static void main(String[] args) {
// AtomicInteger atomicInteger = new AtomicInteger(2020);
//初始值 和 时间戳 类似于版本号
//注意:如果泛型是包装类,注意对象的引用问题
AtomicStampedReference<Integer> atomicInreger = new AtomicStampedReference<>(1,1);
//乐观锁的原理问题
new Thread(()->{
int stamp = atomicInreger.getStamp();//获得版本号
System.out.println("a1"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicInreger.compareAndSet(1, 2, atomicInreger.getStamp(), atomicInreger.getStamp() + 1));
System.out.println("a2"+atomicInreger.getStamp());
System.out.println(atomicInreger.compareAndSet(2, 1, atomicInreger.getStamp(), atomicInreger.getStamp() + 1));
System.out.println("a3"+atomicInreger.getStamp());
},"a").start();
new Thread(()->{
int stamp = atomicInreger.getStamp();//获得版本号
System.out.println("b1"+stamp);
System.out.println(atomicInreger.compareAndSet(1, 6, stamp, stamp + 1));
System.out.println("b1"+atomicInreger.getStamp());
},"b").start();
}
}