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

相关推荐
吃西瓜的年年15 小时前
5.C语言流程控制语句
c语言·开发语言
萧曵 丶15 小时前
Java 泛型详解
java·开发语言·泛型
码上宝藏15 小时前
从解耦到拓展:Clapper 0.10.0 插件化架构设计与 Lua 脚本集成
linux·开发语言·lua·视频播放器·clapper
努力学算法的蒟蒻15 小时前
day50(12.31)——leetcode面试经典150
面试·职场和发展
qq_1171790715 小时前
海康威视球机萤石云不在线问题解决方案
开发语言·智能路由器·php
superman超哥15 小时前
Rust 并发性能调优:线程、异步与无锁的深度优化
开发语言·后端·rust·线程·异步·无锁·rust并发性能
csbysj202015 小时前
Python 多线程
开发语言
superman超哥15 小时前
Rust Trait 对象与动态分发权衡:性能与灵活性的深度权衡
开发语言·后端·rust·rust trait·对象与动态发布·性能与灵活性
ftpeak15 小时前
Burn:纯 Rust 小 AI 引擎的嵌入式物体识别之旅(一步不踩坑)
开发语言·人工智能·rust
独断万古他化15 小时前
【Spring Web MVC 入门实战】实战三部曲由易到难:加法计算器 + 用户登录 + 留言板全流程实现
java·后端·spring·mvc