多线程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问题

相关推荐
哦虎!3 小时前
【JavaEE】网络初识
java
for_ever_love__3 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
西柚小萌新3 小时前
【岗位面试】--成都博维数孪 - 工业 AI 解决方案顾问
人工智能·面试·职场和发展
小 黄 鸡4 小时前
Flutter 面试必会知识点详解(从基础到进阶)
flutter·面试·职场和发展
程序猿追4 小时前
kotlin-retry 接入鸿蒙后,怎样确认它真的会停止重试
开发语言·kotlin·harmonyos
我是人✓4 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
智能直播4 小时前
网络RTMP拉流不卡顿、声音不同步,一文讲透缓冲区、时间戳
开发语言·ffmpeg·php·音视频·视频编解码
欣栀♡4 小时前
JVM 频繁 Full GC 先看日志括号里的 cause,jstat 的 FGC 在 JDK 8 上会骗人
java·jvm
IT研究室4 小时前
最新计算机毕业设计选题推荐-基于spring boot的葡萄酒文化宣传网站-网站-文档指导-Java-springboot
java·spring boot·课程设计
慧都小项4 小时前
MyEclipse 中创建和测试 JAX-RS REST 接口:从项目配置到 REST Explorer
java·restful·myeclipse·jax-rs