多线程CAS八股文

是啥?

CAS 比较和交换(compare and swap),一个CAS有三个操作

  1. 比较内存和寄存器1的值是否相等
  2. 如果相对,就把寄存器2的值写入内存
  3. 返回操作是否成功

本质上是CPU的指令,设计到的操作不是原子性的,但是由于这个指令的原子性的,所以整体就是原子性的。

在这段代码中,可以把address理解为内存,expectValue是寄存器1,swapValue是寄存器2,首先会判断address的值是否和expectValue的值是否相等,如果是相等,就会把swapValue的值给写入到内存中去。

CAS本质是CPU的指令,操作系统对他进行了一些封装,提供一些api给c++使用,JVM又是基于C++实现的,所以JVM中也可以调用CAS的操作。

CAS的主要用途:实现原子类

在JAVA标准库中,在java.util.concurrent.atomic中

提供这些原子类,可以实现在不加锁的情况下解决线程安全问题同时又可以提高性能

在这段代码中,首先需要实例化一个CAS对象AtomicInteger对象,然后不需要进行加锁,创建两个线程让他们分别去进行自增5000,可以看出最后并没有出现线程安全问题且这个程序的正常退出,退出码为code0.

点开具体的实现就会发现,这个就是调用了JVM封装好了的CAS

为什么CAS能够保证线程安全?

Value内存的值,oldvalue寄存器的值

CAS会判断内存的值是否和寄存器一样,如果是的话就会进行修改,如果不是就会返回false然后就进入循环体进行重新读取

假设现在存在两个线程

第一个线程现在内存中读取到value为0,然后这个时候随机调度导致线程2开始执行,他因为寄存器和内存是一样的,所以就触发修改操作,把内存修改成1,同时把自己寄存器在内存中读取成1,因为第一个线程会去读取内存,发现不一样就不会修改,会去重新把内存中的值读取到寄存器再修改,这就保证了线程的安全

使用CAS实现自旋锁

在这段使用CAS模拟实现自旋锁的代码中,首先是创建了一个空线程,然后写一个lock和unlock方法。在lock中使用CAS反复的去读内存和寄存器,如果不一样就一直自旋等待,直到另外一个线程释放锁,如果一样就把Thread.currentThread赋值给this.owner。

CAS的ABA问题

ABA问题是啥?

举个例子:

我们知道CAS的工作模式是先判断内存和寄存器的值,一样才会进行修改,现在假设你的账户有1000块,某天你去ATM机取钱,这个时候你要取500,由于卡了一下,所以多按了几下,导致多了几个线程,他们都是会执行扣款500的操作,这个时候第一个线程成功了,你被扣了500块钱,现在你的账户只有500,恰巧在这个时候,老妈给你转了500块,这个时候你的账户又变成了1000块,由于CAS的工作模式是在内存和寄存器之间进行比较,这个时候发现还是1000块,又执行了扣款500,这个时候相当于我只取出了500,但是被扣款了1000,这个就叫做CAS的ABA问题

如何解决CAS的ABA问题

在上述取钱的过程中,之所以会出现ABA问题,是因为我们使用钱作为中间值来判断是否有线程穿插进行修改余额,这个余额是可加可减的,所以会出现ABA问题,如何解决呢,我们可以规定只能➕不能➖,从而规避这个问题,如何解决呢?引入一个"版本号"

我们规定版本号从1开始,没进行一次修改那版本号就要加1,还是取钱的例子,首先,我们去取出500块,虽然我们多按了几次产生了多个线程,因为版本号的问题,我们一开始取出了500块这个时候版本号是1,而碰巧这个时候老妈给我转了500块,版本号是2,这个时候虽然账户变成了1000块,但是因为之前的线程针对的是版本号,所以他们会去比较版本号为1的时候的余额,发现这个时候确实是500,不是1000,所以就退出,也就可以规避CAS的ABA问题

相关推荐
程序员天天困1 分钟前
后端视角看 EventBus:发布订阅总线的原理、场景与用法
java·后端
要开心吖ZSH9 分钟前
AI医疗分诊与健康咨询助手agent开发——(4-2)从零到一:我给AI医疗分诊助手加了个“知识库大脑“,终于搞懂了RAG是什么
java·docker·agent·医疗·rag
Ulyanov1 小时前
Python实现6-DOF刚体仿真器(下)——环境扰动与控制闭环
开发语言·python·算法·系统仿真·雷达电子对抗·导引头
分布式存储与RustFS1 小时前
RustFS Beta.10 性能解读:PUT 全面反超 MinIO,Rust 重写对象存储成了?
开发语言·后端·rust
小小的木头人1 小时前
Python 批量解析 Excel 经纬度,调用高德地图 API 获取中文地址
开发语言·python·excel
怎么比啊都是大神2 小时前
关于==null、isEmpty()和StrUtil.isBlank()
java
唐青枫2 小时前
Java Neo4j 实战指南:从图模型、Cypher 到 Spring Boot 关系查询
java
观远数据2 小时前
从离线开发到实时同步:DataFlow如何支撑企业级数据治理闭环
java·windows·microsoft·excel
nzz_1712142 小时前
PHP程序员转型AI岗位指南:核心技能、北京就业市场与转型路径分析
开发语言·人工智能·php
Risehuxyc3 小时前
C# 将doc转换为docx
开发语言·c#·xhtml