多线程进阶-JUC

28 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天

1.深入理解CSA

什么是CSA

大厂必须深入研究底层!!!!修内功!操作系统、计算机网络原理、组成原理、数据结构

 public class casDemo {
     //CAS : compareAndSet 比较并交换
     public static void main(String[] args) {
         AtomicInteger atomicInteger = new AtomicInteger(2020);
 ​
         //boolean compareAndSet(int expect, int update)
         //期望值、更新值
         //如果实际值 和 我的期望值相同,那么就更新
         //如果实际值 和 我的期望值不同,那么就不更新
         System.out.println(atomicInteger.compareAndSet(2020, 2021));
         System.out.println(atomicInteger.get());
 ​
         //因为期望值是2020  实际值却变成了2021  所以会修改失败
         //CAS 是CPU的并发原语
         atomicInteger.getAndIncrement(); //++操作
         System.out.println(atomicInteger.compareAndSet(2020, 2021));
         System.out.println(atomicInteger.get());
     }
 }
 ​

image-20221012193623988

Unsafe类

image-20221012194236654

image-20221012194340889

总结:

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

缺点:

  • 循环会耗时;
  • 一次性只能保证一个共享变量的原子性;
  • 它会存在ABA问题

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

image-20221012195305957

线程1:期望值是1,要变成2;

线程2:两个操作:

  • 1、期望值是1,变成3
  • 2、期望是3,变成1

所以对于线程1来说,A的值还是1,所以就出现了问题,骗过了线程1;

 public class CSADemo {
 ​
 ​
     //CAS  compareAndSet : 比较并交换!
     public static void main(String[] args) {
         AtomicInteger atomicInteger = new AtomicInteger(2020);
 ​
         atomicInteger.compareAndSet(2020,2021);
         System.out.println(atomicInteger.get());
 ​
         atomicInteger.compareAndSet(2021,2020);
         System.out.println(atomicInteger.get());
 ​
 ​
         atomicInteger.compareAndSet(2020,2021);
         System.out.println(atomicInteger.get());
     }
 ​
 }

2.原子引用

解决ABA问题,对应的思想:就是使用了乐观锁~

带版本号的 原子操作!

Integer 使用了对象缓存机制,默认范围是-128~127,推荐使用静态工厂方法valueOf获取对象实例,而不是new,因为valueOf使用缓存,而new一定会创建新的对象分配新的内存空间。

image-20221012201755130

所以如果遇到,使用大于128的时候,使用原子引用的时候,如果超过了这个值,那么就不会进行版本上升

image-20221012202010221

那么如果我们使用小于128的时候:

image-20221012202026355

正常业务操作中,我们一般使用的是一个个对象,一般情况不会遇到这种情况。