2023.10.26 关于 CAS 和 ABA 问题

news2024/10/6 0:32:25

目录

CAS 操作

执行过程

 CAS 应用场景

实现原子类

实现自旋锁

ABA 问题 


CAS 操作

  • 全称 Compare and swap ,译为 比较并交换

执行过程

我们假设内存中的原始数据 V,旧的预期值 A,需要修改的新值 B

  • 比较 A 与 V 是否相等
  • 如果比较相等,将 B 写入 V
  • 返回操作是否成功

  • 此处如果 A 和 V 的值不同,则无事发

伪代码

  • 以下是变量自增的伪代码,其不能编译运行,仅表达了一个大概的逻辑思路,方便理解
class AtomicInteger {
    private int value;
    public int getAndIncrement() {
//      将内存中的 value 值读取到寄存器 A 中
        int oldValue = value;
        while ( CAS(value, oldValue, oldValue+1) != true) {
            oldValue = value;
       }
        return oldValue;
   }
}
  • oldValue 可以理解为寄存器中的 A 的值
  • 即先把 内存中的 value 读到寄存器 A 中
  • oldValue+1 可以理解为另一个寄存器 B 的值
  • 此处的 while 循环,是为保证仅当寄存器中 A 和 内存中 value 相等,才能进行 将寄存器 B 值写入内存 value 中
  • 如果不同,则返回 false,然后重写读取内存中的 value 并放入寄存器 A 中,继续进入 while 循环
  • 可能导致 寄存器 A 和 value 不相等的原因是:

  • 寄存器 A 读取完 value 后,线程发生了切换,另一线程,对内存 value 值进行了修改,再等到该线程回来时,进行 CAS 判定,此时的 value 和 A 便不相等

注意:

  • 上述 CAS 操作的执行过程,并非是通过一段代码实现的,而是通过 一条 CPU 指令 完成
  • 即 CAS 操作是 原子的
  • 所以相较于加锁操作,CAS 操作在一定程度上也能够解决线程安全问题

 CAS 应用场景

实现原子类

  • 以下是通过原子类来保证多线修改同一变量的安全性
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadDemo29 {
    public static void main(String[] args) throws InterruptedException {
//        这些都是原子类,就是基于 CAS 实现了 自增,自减操作
//        此时进行这类操作不需要加锁,也是线程安全的
        AtomicInteger count = new AtomicInteger(0);

//        使用原子类,来解决线程安全问题
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
//                因为 java 不支持运算符重载,所以只能使用方法来表示自增自减
                count.getAndIncrement(); // count++
                // count.incrementAndGet(); // ++count
                //count.getAndDecrement(); // count--
                //count.decrementAndGet(); // --count
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                count.getAndIncrement();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("count 的值为:" + count.get());
    }
}

运行结果:


实现自旋锁

自旋锁原理

  • 当锁被其他线程拥有时,另外的线程不会挂起等待,而是会反复询问,看当前锁是否被释放,整个过程为纯用户态的轻量级锁

伪代码

  • 以下是实现自旋锁的伪代码,其不能编译运行,仅表达了一个大概的逻辑思路,方便理解
public class SpinLock {
    private Thread owner = null;//表示当前锁是谁的
    public void lock(){ 
        while(!CAS(this.owner, null, Thread.currentThread())){
            
       }
   }
    public void unlock (){
        this.owner = null;
   }
}

图解理解:

  • 监测当前的 owner 是否为 null,如果是 null,就进行交换,也就是把当前线程的引用赋值给 owner
  • 如果赋值成功,此时循环结束,加锁完成
  • 如果当前锁已经被其他线程占用,CAS 便会发现 this.owner 不为 null,CAS 便不会进行赋值,同时返回 false,循环继续执行,进行下次判定

ABA 问题 

  • CAS 操作执行的核心为 检查比较 value 和 oldValue 的值是否相等
  • 如果相等,就视为 value 中途未被其他线程修改,所以进行下一步交换操作是没问题的
  • 但是 这里的相等也可能是 value 值先被修改,再被还原从而导致 value 和 oldValue 值相等
  • 所以 value 和 oldValue 的值相等,并不代表 value 值一定未被修改
  • 所以 CAS 操作 存在 ABA 问题
  • 即  value 值可能最先为 A ,后被其它线程修改为 B ,又被其他线程重新修改回 A,导致 CAS 操作误以为 value 值未被修改,从而进行其交换操作

注意:

  • ABA 问题在大部分情况下,并不会对代码或逻辑造成太大影响
  • 但是还是存在一些极端情况

实例理解

解决方案

  • 针对当前问题,我们可以加入一个版本号
  • 即初始版本号为 1,每次进行修改时,其版本号均 +1
  • 进行 CAS 时,不再以金额为判定基准,而是以版本号为基准
  • 此时版本号要是没变,就一定未发生修改
  • 因为版本号只能增加,不能减少

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1136763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot日志+SpringMVC+UUID重命名文件+Idea热部署

目录 【SpringBoot日志】 什么是日志&#xff0c;日志的作用 关于日志的基本信息&#xff0c;又有哪些呢&#xff1f; 关于日志的级别 Springboot内置SLF4J【门面模式】 和 logback【日志框架】 在配置文件中可以设置日志级别【以.yml为例】 SpringBoot 持久化的保存日…

QT图形视图框架绘制曲线图和Smith图

QT图形视图框架绘制曲线图和Smith图 QGraphicsView是Qt框架中的一个图形视图部件&#xff0c;用于显示和处理2D图形元素。它提供了强大的工具来创建交互式和自定义的图形应用程序。在绘制折线图和Smith图时&#xff0c;使用QGraphicsView有以下一些优点&#xff1a; 交互性&am…

二叉树题目:最大二叉树 II

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;最大二叉树 II 出处&#xff1a;998. 最大二叉树 II 难度 5 级 题目描述 要求 如果一个树满足其中每个结点的值…

【Python学习】—Python基础语法(六)

一、数据容器 Python中的数据容器&#xff1a;一种可以容纳多份数据的数据类型&#xff0c;容纳的每一个元素&#xff0c;可以是任意类型的数据&#xff0c;如字符串、数字、布尔等。 二、list列表 列表的下标索引 嵌套列表的下标 my_list[aaa,1,True] print(my_list[0]) p…

电压检测芯片如何发挥作用,保护电路?纳米软件为您介绍工作原理

电压检测芯片是一种常见的集成电路芯片&#xff0c;用来监测电路中的电压变化&#xff0c;防止电路受到过电压和欠电压的损坏。电源电压检测芯片被广泛应用于各种电子设备中&#xff0c;比如手机、电脑、家电等&#xff0c;在电压监测、电源管理、电池电量检测、温度检测、电压…

3D模型怎么贴法线贴图?

1、法线贴图的原理&#xff1f; 法线贴图&#xff08;normal mapping&#xff09;是一种计算机图形技术&#xff0c;用于在低多边形模型上模拟高多边形模型的细节效果。它通过在纹理坐标上存储和应用法线向量的信息来实现。 法线贴图的原理基于光照模型。在渲染过程中&#x…

云表低代码:数字化转型的新风口,你了解多少?

自2019年起&#xff0c;低代码开发平台骤然引发热议&#xff0c;成为了科技领域的新宠。关于其定义和影响力&#xff0c;众说纷纭。有人将它誉为第四代编程语言&#xff0c;有人视它为开发模式的颠覆者&#xff0c;更有人认为它引领了企业管理模式的变革。这股热潮在社区内引发…

BIOS MBR UEFI GPT详解

先来看下名词 启动方式&#xff1a; Legacy&#xff1a;传统的。指的就是BIOS。 BIOS&#xff1a;Basic Input Output System&#xff0c;中文名称"基本输入输出系统"。 UEFI&#xff1a;Unified Extensible Firmware Interface&#xff0c;中文名称"统一的…

获取IEEE会议论文的标题和摘要

获取IEEE会议论文的标题和摘要 – 潘登同学的爬虫笔记 文章目录 获取IEEE会议论文的标题和摘要 -- 潘登同学的爬虫笔记 打开IEEE的高级搜索环境准备完整爬虫过程获取文章地址翻译函数获取文章标题和摘要 前几天接到导师的一个任务&#xff0c;要我去找找IEEE Transactions on K…

用低代码平台代替Excel搭建进销存管理系统

目录 一、用低代码平台搭建系统 1.需求调研 2.基于痛点梳理业务流程 3.低代码实现 &#xff08;1&#xff09;基础资料模块 &#xff08;2&#xff09;采购管理模块 &#xff08;3&#xff09;销售管理模块 &#xff08;4&#xff09;库存管理模块 &#xff08;5&…

快手联合阿里云构建容器混合云架构,轻松应对百万级秒杀

云布道师 摘要&#xff1a;快手电商在 2023 年某大 V 大促直播活动中&#xff0c;首次采用混合云弹性调度架构&#xff0c;应对大 V 百万级别秒杀峰值的计算资源需求。此次为【快手容器云 阿里云】的深度技术结合&#xff0c;在【快手电商直播秒杀】场景下的大规模首次应用。既…

Calcite 解析层详解

1、概述 用户的操作请求经过服务层的接收和封装被传递给calcite-core模块。 其中第一站就是解析层&#xff0c;它的作用主要是对SQL语句进行语法解析。 在这个过程中&#xff0c;初始的SQL字符串会被转化为Calcite内部的语法解析节点&#xff0c;为进一步的语法校验和优化做…

建筑木模板厂家直销 915*1830*15mm酚醛面板规格

建筑木模板在建筑施工中扮演着重要的角色&#xff0c;它是支撑混凝土浇筑和保证建筑结构稳定性的关键材料。作为一家专业的建筑木模板厂家直销商&#xff0c;我们引以为傲地推出了915*1830*15mm酚醛面板规格的产品。 我们的建筑木模板采用高质量的酚醛树脂胶粘剂和优质桉木木材…

低代码平台是什么意思?低代码平台如何设计与实现?

低代码这个词&#xff0c;也许许多人都相当陌生。低代码的正式提出可以追溯到2014年&#xff0c;当时全球最具影响力的独立研究咨询公司Forrester&#xff0c;正式界定了低代码的概念。低代码指可通过最少的手工编程就能快速交付应用程序&#xff0c;并能快速设置和部署用于参与…

centos启动tomcat 并指定jdk 版本

在tomcat的catalina.sh文件手动设置JAVA_HOME变量即可 例如&#xff1a; 前提是文件存在 保存配置重新启动tomcat

短说通用版V4.1.0测试版发布|新增全新马甲模块等新功能

大家好&#xff0c; 我是给你们带来惊喜的运营小番茄。 本期更新为短说通用版 4.1.0测试版。 本次V4.1.0版本新增功能有&#xff1a; ①学院免费课程支持发布评价 ②商城子系统商品支持使用积分抵扣 ③新增管理后台查看和导出评论功能 ④支持设置积分类型展示排序功能 …

记录一次时序数据库的实战测试

0x1.前言 ​ 本文章仅用于信息安全防御技术分享&#xff0c;因用于其他用途而产生不良后果&#xff0c;作者不承担任何法律责任&#xff0c;请严格遵循中华人民共和国相关法律法规&#xff0c;禁止做一切违法犯罪行为。文中涉及漏洞均以提交至教育漏洞平台。 0x2.背景 ​ 在某…

99%的时间里使用的14个git命令

学习14个Git命令&#xff0c;因为你将会在99%的时间里使用它们 必须了解的命令整理 1&#xff0c;git init 初始化一个新的Git仓库。 这将在当前目录中创建一个名为".git"的子目录&#xff0c;Git会将所有仓库的元数据存储在其中。 2&#xff0c;git clone 克隆…

【unity3D】Rect Transform组件

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是unity的Rect Transform组件 Rect Transform组件 基础知识详细介绍补充 基础知识 Rect Transform是Unity中的一个UI组件&#xff0c;用于…

商淘云:如何选择开源B2B2C多用户商城系统

选择开源B2B2C多用户商城系统是一个关键的决策&#xff0c;因为它将直接影响到您的电子商务平台的性能、功能和用户体验。以下是一些指导原则&#xff0c;可帮助您做出明智的选择。 首先&#xff0c;考虑系统的稳定性和安全性 选择一个经过广泛测试和验证的开源系统&#xff0…