厚积薄发打卡Day49:狂神说Java之JUC并发编程<CAS入门到“锁“小结>(下)

前言:

众所周知,B站是全中国最大的在线学习平台,此次学习打卡的教程来自【狂神说】与【寒食君】两位B站up主,欢迎大家一键三连🚀

学习视频来源:

  1. 【狂神说Java】JUC并发编程最新版通俗易懂
  2. 寒食君:Java并发系列

博客回顾:

  1. Day26:狂神说Java之JUC并发编程<代码+笔记>(上)
  2. Day27:狂神说Java之JUC并发编程(中)——从 JMM 到 volatile

前置知识:学习JUC前需要对java的多线程有一定的掌握。

学习视频:

【狂神说Java】多线程详解

详细资料可参考博客:狂神说Java之多线程详解<全网最全(代码+笔记)>

0. 学习方法

源码+官方文档:

其实官方文档就是源码编译出来的,其本质还是看源码,不过文档会比较方便学习

19. 理解CAS

什么是CAS :
CAS 是 Compare And Swap的简称,从字面上理解就是比较并更新,简单来说:从某一内存上取值V,和预期值A进行比较,如果内存值V和预期值A的结果相等,那么我们就把新值B更新到内存,如果不相等,那么就重复上述操作直到成功为止。

在 Java的原子类中,有对cas的封装进行应用:此处用 AtomicInteger 举例

public class CAS_Demo {
   

    public static void main(String[] args) {
   
        AtomicInteger atomicInteger = new AtomicInteger(2020);

        //CAS的封装体现:compareAndSet 比较并赋值
        //比较当前值是否为2020? set 2021,return true : do nothing,return false
        System.out.println(atomicInteger.compareAndSet(2020, 2021));//true
        System.out.println(atomicInteger.get());//此时为2021

        //获取值并自增
        atomicInteger.getAndIncrement();//自增后为 2022
        System.out.println(atomicInteger.compareAndSet(2021, 2033));//false
        System.out.println(atomicInteger.get());// 2022
    }
}

点击查看AtomicInteger的源码:
直接通过Unsafe类调用底层 CAS方法

//compareAndSet
public final boolean compareAndSet(int expect, int update) {
   
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

//getAndIncrement  
public final int getAndIncrement() {
   
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

在这里插入图片描述

getAndAddInt方法详解:

在这里插入图片描述

通过一定的轮询,也就是后面介绍的自旋锁:

在这里插入图片描述

CAS锁其又称作Java的乐观锁,但是我们可以看到其实质上是没有上🔒的,只是赋值的过程前多了一个比较的方法,因此可能引起一定的ABA问题:
[狸猫换太子] 如果另一个线程修改V值假设原来是A,先修改成B,再修改回成A。当前线程的CAS操作无法分辨当前V值是否发生过变化。

举个栗子:
在你非常渴的情况下你发现一个盛满水的杯子,你一饮而尽。之后再给杯子里重新倒满水。然后你离开,当杯子的真正主人回来时看到杯子还是盛满水,他当然不知道是否被人喝完重新倒满。

public class CAS_Demo {
   
    public static void main(String[] args) {
   
        AtomicInteger atomicInteger = new AtomicInteger(2020);
        // 我们想把数字改成6666
        // ============== 捣乱的线程 ==================
        atomicInteger.compareAndSet(2020, 2021);
        System.out.println("such a fool...");
        atomicInteger.compareAndSet(2021, 2020);

        // ============== 期望的线程 ==================
        System.out.println(atomicInteger.compareAndSet(2020, 6666));
        System.out.println(atomicInteger.get(
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值