1、深入理解CAS
package com.zkw.JUC并发编程.cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CasDemon {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// 期望的值,新的值
// public final boolean compareAndSet(int expectedValue, int newValue)
// 如果我期望的直达到了,那么就更新,否则,就不更新 CAS 是CPU的并发原语!
System.out.println(atomicInteger.compareAndSet(2020, 2021));
System.out.println(atomicInteger.get());
atomicInteger.getAndIncrement();//+1的操作
System.out.println(atomicInteger.compareAndSet(2020, 2021));
System.out.println(atomicInteger.get());
}
}
CAS:比较当前工作内存中的值,如果是期望的,那么执行操作!,如果不是就一直循环。
缺点:
1、循环耗时
2、一次只能保证一个共享变量的原子性
3、会导致ABA问题
2、原子引用
解决ABA问题,引入原子引用!对应的思想:乐观锁
package com.zkw.JUC并发编程.cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
public class CasDemon01 {
// AtomicStampedReference 注意,如果泛型是一个包装类,注意对象的引用问题
public static void main(String[] args) {
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);
new Thread(()->{
int stamp = atomicStampedReference.getStamp();//获得版本号
System.out.println("A1=>"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(1, 2,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
System.out.println("A2=>"+atomicStampedReference.getStamp());
System.out.println(atomicStampedReference.compareAndSet(2, 1,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
System.out.println("A3=>"+atomicStampedReference.getStamp());
},"A").start();
// 与乐观锁的原理一样
new Thread(()->{
int stamp = atomicStampedReference.getStamp();//获得版本号
System.out.println("B1=>"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(1, 6
, stamp, stamp + 1));
System.out.println("B1=>"+atomicStampedReference.getStamp());
},"B").start();
}
}
Integer使用了对象缓存机制,默认范围是 -128~127,推荐使用静态工厂valueof获取对象的实例,而不是 new,因为 valueof使用缓存,而 new 一定会创建新的对象分配新的内存空间。
缓存机制,默认范围是 -128~127,推荐使用静态工厂valueof获取对象的实例,而不是 new,因为 valueof使用缓存,而 new 一定会创建新的对象分配新的内存空间。**