什么是CAS

Unsafe 类

深入理解CAS_原语

深入理解CAS_乐观锁_02

打断点发现this + 偏移量 不等 var5

则不自增,返回 var5

深入理解CAS_java_03

自旋锁:

深入理解CAS_sql_04

CAS : ABA 问题:(狸猫换太子)

CAS : 比较当前工作内存中的值和主内存中的值,如果这个值是期望的,那么则执行操作,否则不执行!如果不是则一直循环

优点:自带原子性

缺点:循环比较耗时,一次性只能保证一个g共享变量的原子性,ABA 问题

ABA 问题

左边A 线程,右边B线程,B线程将1 期望值改为3,又将 3 改为1 ,A 最终还是1 ,但是 左边A 线程看到的值还是A =1

深入理解CAS_版本号_05

package com.cas;

import java.util.concurrent.atomic.AtomicInteger;

public class CASDemo {


//CAS 缩写就是compareAndSet : 比较并交换!
public static void main(String[] args) {

//对于我们平时写的SQL: 乐观锁

AtomicInteger atomicInteger = new AtomicInteger(2020);
//CAS
//期望,更新
//public final boolean compareAndSet(int expect,int update)
//如果我期望的值达到了,那么就更新,否则,就不更新,CAS 是CPU 的并发原语!
//=======捣乱的线程==
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(atomicInteger.compareAndSet(2020, 2021));
System.out.println(atomicInteger.get());

// System.out.println(atomicInteger.getAndIncrement());
//如果再设置一次能期望成功吗
// System.out.println(atomicInteger.compareAndSet(2020, 2021));
// System.out.println(atomicInteger.get());



}
}

如何就觉ABA 问题?

用原子引用解决

原子引用

解决ABA 问题,引用原子引用!对应的思想! 就是乐观锁!

带版本号 的原子操作

注意:正常在业务操作,这里面比较的都是对象,

深入理解CAS_版本号_06

深入理解CAS_版本号_07

package com.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

public class CASDemo {


//CAS 缩写就是compareAndSet : 比较并交换!
public static void main(String[] args) {

//对于我们平时写的SQL: 乐观锁

//AtomicInteger atomicInteger = new AtomicInteger(2020);

//参数:初始值,版本号
//AtomicStampedReference 注意:如果泛型是一个包装类,注意对象的引用问题
AtomicStampedReference<Integer> atomicInteger = new AtomicStampedReference<>(1,1);

new Thread(()->{
int stamp =atomicInteger.getStamp(); //获得版本号
System.out.println("a1=>"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
//执行完versioN +1
System.out.println(atomicInteger.compareAndSet(1, 2, atomicInteger.getStamp(), atomicInteger.getStamp() + 1));
System.out.println("a2=>"+atomicInteger.getStamp());
System.out.println(atomicInteger.compareAndSet(2, 1, atomicInteger.getStamp(), atomicInteger.getStamp() + 1));
System.out.println("a3=>"+atomicInteger.getStamp());
},"A").start();

new Thread(()->{
int stamp =atomicInteger.getStamp(); //获得版本号
System.out.println("b1=>"+atomicInteger.getStamp());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicInteger.compareAndSet(1, 6, stamp, stamp + 1));
System.out.println("b1=>"+atomicInteger.getStamp());

},"B").start();



// //CAS
// //期望,更新
// //public final boolean compareAndSet(int expect,int update)
// //如果我期望的值达到了,那么就更新,否则,就不更新,CAS 是CPU 的并发原语!
// //=======捣乱的线程==
// 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(atomicInteger.compareAndSet(2020, 2021));
// System.out.println(atomicInteger.get());
//
// // System.out.println(atomicInteger.getAndIncrement());
// //如果再设置一次能期望成功吗
// // System.out.println(atomicInteger.compareAndSet(2020, 2021));
// // System.out.println(atomicInteger.get());



}
}

输出结果:

a1=>1

b1=>1

true

a2=>2

true

a3=>3

false

b1=>3

总结:原子引用解决ABA 问题