什么是CAS?
CAS:比较当前工作内存的值和主内存的值,如果这个值是期望的,那么执行操作,如果不是就一直循环
缺点:
1.循环会耗时
2.一次性只能保证一个共享变量的原子性
3.ABA问题
package com.xizi.cas;
import java.util.concurrent.atomic.AtomicInteger;
//CAS CompareAndSet :比较并交换
public class Cas {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
//期望更新
// public final boolean compareAndSet(int expect,int update)
// 如果我期望的值达到了,那么就更新,否则就不更新
System.out.println(atomicInteger.compareAndSet(2020, 2021));//true
System.out.println(atomicInteger.get());//2021
// atomicInteger.getAndIncrement();
System.out.println(atomicInteger.compareAndSet(2020, 2021));//false
System.out.println(atomicInteger.get());//2021 不更新
}
}
Unsafe类
ABA问题
package com.xizi.cas;
import java.util.concurrent.atomic.AtomicInteger;
//CAS CompareAndSet :比较并交换
public class Cas {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
//期望更新
// public final boolean compareAndSet(int expect,int update)
// 如果我期望的值达到了,那么就更新,否则就不更新 CAS是CPU的并发原语
System.out.println("===========捣乱的线程==========");
System.out.println(atomicInteger.compareAndSet(2020, 2021));
System.out.println(atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(2021, 2020));
System.out.println(atomicInteger.get());
System.out.println("========期望的线程============");
System.out.println(atomicInteger.compareAndSet(2020, 6666));
System.out.println(atomicInteger.get());
}
}
原子引用解决ABA问题, 带版本号的原子引用
package com.xizi.cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
public class CASdemo {
// AtomicStampedReference 如果泛型是包装类,注意对象的引用问题
//正常业务,这里是一个对象,唯一的
static AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference<>(1,1);
public static void main(String[] args) {
new Thread(()->{
int stamp = atomicStampedReference.getStamp();//获取版本号
System.out.println("a1=>"+stamp);
try {
TimeUnit.SECONDS.sleep(1);
} 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("b2=>"+atomicStampedReference.getStamp());
},"b").start();
}
}