17.1、什么是CAS
package com.chen.cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
// CAS compareAndSet:比较并交换
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// except:期望、update:更新
// public final boolean compareAndSet(int expect, int update)
// 如果我期望的值达到了,那就更新,否则就不更新,CAS 是CPU的并发原语
atomicInteger.compareAndSet(2020,2021);
System.out.println(atomicInteger.get());
atomicInteger.compareAndSet(2020,2021);
System.out.println(atomicInteger.get());
}
}
17.2、Unsafe类
CAS:比较当前工作内容的值和主内存中的值,如果这个值是期望的,那么就执行操作!如果不是,就一直循环。
缺点:
1、循环会耗时
2、一次性只能保证一个共享变量的原子性
3、ABA问题
17.2、ABA问题
package com.chen.cas;
import java.util.concurrent.atomic.AtomicInteger;
public class CASDemo {
// CAS compareAndSet:比较并交换
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// except:期望、update:更新
// public final boolean compareAndSet(int expect, int update)
// 如果我期望的值达到了,那就更新,否则就不更新,CAS 是CPU的并发原语
// ==================捣乱的线程=================
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());
}
}
17.3、原子引用
解决ABA问题,映入原子引用!对应的思想:乐观锁
带版本号的原子操作!
注意:
Integer使用了对象缓存机制,默认范围是-128~127,推荐适用静态工厂方法valueOf获取对象实例,而不是new,因为valueof使用缓存,而new一定会创建新的对象分配新的内容空间。
package com.chen.cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
public class CASDemo {
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("a2=>" + 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("b2=>" + atomicStampedReference.getStamp());
},"b").start();
}
}