当前位置: 首页 > news >正文

自旋锁与CAS

上文我们认识了许许多多的锁,此篇我们的CAS就是从上文的锁策略开展的新概念,我们来一探究竟吧

1. 什么是CAS?

CAS: 全称Compare and swap,字⾯意思:“比较并交换”,⼀个CAS涉及到以下操作:
我们假设内存中的原数据V,旧的预期值A,需要修改的新值B。

  1. 比较A与V是否相等。(比较)
  2. 如果比较相等,将B写入V。(交换)
  3. 返回操作是否成功。

CAS伪代码
下面写的代码不是原子的,真实的CAS是⼀个原子的硬件指令完成的.这个伪代码只是辅助理解CAS的工作流程.

while{boolean CAS(address, expectValue, swapValue) {if (&address == expectedValue) {&address = swapValue;return true;}return false;}
}

说明:

  1. address: 表示要修改的内存地址
  2. expectValue: 预期值
  3. swapValue:要设置的新值

执行流程:

  1. 用一个预期值去和内存中的值做比较
  2. 如果预期值与内存中的值相等,就用新的值更新内存中的值
  3. 如果预期值与内存中的值不相等,就用进入下一次比较

我们前面学习过的线程安全问题是由于CPU的随机调度导致的,我们的处理方法是给有关修改共享变量的代码块加了synchronize关键字,保证了原子性,解决了线程安全问题,
那么问题来了,
为什么我们看到的CAS伪代码并没有保证原子性,那么他是如何保证原子性的呢??

我们从一段例子来讲解:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总结:

  1. CAS对应的是硬件指令cmpxchg从CPU做了原子性支持,与LOCK 、UNLOCK 指令同地位
  2. CAS操作每次读取(LOAD)数据是从主内存中读取,并没有对应的工作内存
  3. 自旋锁是通过while把CAS进行包裹,让CAS没有成功的时候不停的执行,直到成功执行为止
  4. CAS是一个真正的指令,JVM调用了本地方法之后,对应的CAS指令会在CPU上执行
    执行中LOAD数据会访问主内存

2. CAS实现自旋锁

基于CAS实现更灵活的锁,获取到更多的控制权.
自旋锁伪代码:

public class SpinLock {private Thread owner = null;public void lock(){// 通过CAS 看当前锁是否被某个线程持有.  
// 如果这个锁已经被别的线程持有, 那么就⾃旋等待.  
// 如果这个锁没有被别的线程持有, 那么就把owner 设为当前尝试加锁的线程.  
}}while(!CAS(this.owner, null, Thread.currentThread())){}public void unlock (){this.owner = null;}

3. JDK中基于CAS实现的原子类

说明:

  1. JDK中提供了CAS实现的原子类,我们举其中一种AtomicInteger类来说明
    在这里插入图片描述
  2. 我们调用其中的方法getAndIncrement()
//自增 ++i
atomicInteger.getAndIncrement();
  1. 我们发现getAndIncrement()方法本质是getAndIncrement()
public final int getAndIncrement() {return U.getAndAddInt(this, VALUE, 1);
}
  1. 其中调用了Unsafe这个类的方法,是JDK内部的工具类,不建议外部程序员直接调用
private static final Unsafe U = Unsafe.getUnsafe();
//获取内存中字段在对象中的偏移地址private static final long VALUE= U.objectFieldOffset(AtomicInteger.class, "value");
//1. o表示原子类对象
//2. offset表示内存中字段在对象中的偏移地址
//3. delta表示传入的值
public final int getAndAddInt(Object o, long offset, int delta) {int v;do {//v是CAS操作之前获取的预期值v = getIntVolatile(o, offset);} while (!weakCompareAndSetInt(o, offset, v, v + delta));//while不停的自旋return v;}
   public final boolean weakCompareAndSetInt(Object o, long offset,//内存地址int expected,//预期值int x) {//要设置的值return compareAndSetInt(o, offset, expected, x);//最后调用compareAndSetInt()方法}
//native表示本地方法,即对应了一条CAS指令cmpxchg
public final native boolean compareAndSetInt(Object o, long offset,int expected,int x);
  1. 图解如下:
    在这里插入图片描述

4. CAS的ABA问题

首先我们要知道什么是ABA问题???

ABA的问题:
假设存在两个线程t1和t2.有一个共享变量value,初始值为A.
接下来,线程t1想使用CAS把value值改成Z,那么就需要
先读取value的值,记录到oldValue变量中.
使用CAS判定当前value的值是否为A,如果为A,就修改成Z.
但是,在t1执行这两个操作之间,t2线程可能把value的值从A改成了B,又从B改成了A

举个例子: 今天是疯狂星期四,我和我的女友共用一个小荷包吃饭,我和她说如果小荷包里面有100元 (A状态) 晚上6点就点KFC吃,我怕她忘记了,我就先自己点了,此时,小荷包余额为50元 (B状态) 然后我的朋友疯狂星期四V我50,小荷包的钱又变回了100 (A状态),她再点的时候,发现小荷包还是100元,她就再点了一份,就导致多点了一份KFC

那么我们该如何解决ABA问题呢??
在点KFC的例子当中,我们可以让他查看一下消费记录(版本号),此时的100元是否是开始的100元,
由此可得,我们可以可以给value数据加上一个版本号,当线程2要修改时,不仅要value要符合预期值,同时版本号也要符合
即:
CAS操作在读取旧值的同时,也要读取版本号.
真正修改的时候,

  • 如果当前版本号和读到的版本号相同,则修改数据,并把版本号+1.
  • 如果当前版本号高于读到的版本号.就操作失败(认为数据已经被修改过了).

版本号可以用自增的数值,也可以用随机的UUID,也可以使用时间戳

System.out.println(UUID.randomUUID());

生成随机数:
在这里插入图片描述

相关文章:

自旋锁与CAS

上文我们认识了许许多多的锁,此篇我们的CAS就是从上文的锁策略开展的新概念,我们来一探究竟吧 1. 什么是CAS? CAS: 全称Compare and swap,字⾯意思:“比较并交换”,⼀个CAS涉及到以下操作: 我们假设内存中…...

数组-二分查找

目录 算法思想: 实践: 备注: 二分查找是一种高效的查找算法,适用于在 有序数组 或列表中快速定位目标元素的索引。 重要事情说三遍:使用前提:数组有序,无重复,如果数组未排序&am…...

如何使用 Python 进行文件读写操作?

大家好,我是 V 哥。今天的内容来介绍 Python 中进行文件读写操作的方法,这在学习 Python 时是必不可少的技术点,希望可以帮助到正在学习 python的小伙伴。 以下是 Python 中进行文件读写操作的基本方法: 一、文件读取&#xff1…...

springcloud中的Feign调用

目录 一、基础应用 1.feign使用 1.增加feign依赖 2.编写feign接口 3.启用feign 4.调试 5.可能出现的异常信息 1.404 可能原因: 2.503 可有原因: 2.feign自定义配置 1.创建Feign配置类 2.feign接口 3.调试结果 3.feign多参数请求 Feign是Netflix开发的声明…...

【部署】将项目部署到云服务器

目录 1.获得服务器 2.连接到云服务器 3.配置环境 3.1.Java(运行后端所需) 3.2.MySQL数据库 3.3.Nginx(运行前端所需) 3.4. Node.js(构建前端所需) 4.打包项目 4.1.打包后端项目 4.2.打包前端项目…...

2024年AI大模型技术年度总结与应用实战:创新与突破并进

前言 回顾2024年,我一共发布了286篇博文,粉丝数也达到了43000多。这一年里,我收获颇丰,始终坚持AI大模型的研究方向,并且积极开展大模型的实战应用,也取得了一系列令人振奋的突破。 在286篇博文中&#…...

docker离线安装及部署各类中间件(x86系统架构)

前言:此文主要针对需要在x86内网服务器搭建系统的情况 一、docker离线安装 1、下载docker镜像 https://download.docker.com/linux/static/stable/x86_64/ 版本:docker-23.0.6.tgz 2、将docker-23.0.6.tgz 文件上传到服务器上面,这里放在…...

SuperdEye:一款基于纯Go实现的间接系统调用执行工具

关于SuperdEye SuperdEye是一款基于纯Go实现的间接系统调用执行工具,该工具是TartarusGate 的修订版,可以利用Go来实现TartarusGate 方法进行间接系统调用。 该工具的目标是为了扫描挂钩的NTDLL并检索Syscall编号,然后使用它来执行间接系统调…...

PCL 新增自定义点类型【2025最新版】

目录 一、自定义点类型1、前言2、定义方法3、代码示例二、合并现有类型三、点云按时间渲染1、CloudCompare渲染2、PCL渲染博客长期更新,本文最近更新时间为:2025年1月18日。 一、自定义点类型 1、前言 PCL库自身定义了很多点云类型,但是在使用的时候时如果要使用自己定义的…...

Docker导入镜像

使用命令行进行处理&#xff1a; docker load < onething1_wxedge.tar如下图所示 查看状态 docker images...

PyTorch使用教程(9)-使用profiler进行模型性能分析

1、简介 PyTorch Profiler是一个内置的性能分析工具&#xff0c;可以帮助开发者定位计算资源&#xff08;如CPU、GPU&#xff09;的瓶颈&#xff0c;从而更好地优化PyTorch程序。通过捕获和分析GPU的计算、内存和带宽利用情况&#xff0c;能够有效识别并解决性能瓶颈。 2、原…...

SpringBoot中使用MyBatis-Plus详细介绍

目录 一、MyBatis-Plus的使用步骤 1.引入MybatisPlus的起步依赖 2.定义Mapper&#xff08;也叫dao&#xff09;层的接口 3.MyBatis-Plus中常用注解 4. 使用MyBatis-Plus时要做如下配置 5.条件构造器 Wrapper 一、MyBatis-Plus的使用步骤 1.引入MybatisPlus的起步依赖 M…...

PCL 部分点云视点问题【2025最新版】

目录 一、问题概述二、解决方案1、软件实现2、代码实现三、调整之后博客长期更新,本文最近更新时间为:2025年1月18日。 一、问题概述 针对CloudCompare软件处理过的pcd格式点云,在使用PCL进行特征点提取、配准等实验中最终显示结果出现点云位置偏差较大的问题,本博客给出解…...

【Linux】常见指令(三)

Linux常见指令 01.nano02.cat03.cp04.mv 我的Linux专栏&#xff1a;【Linux】 本节Linux指令讲解的基本框架如下&#xff1a; 大家可以根据自己的需求&#xff0c;自行进行跳转和学习&#xff01; 01.nano nano Linux 系统中一款简单易用的命令行文本编辑器&#xff0c;适合…...

第5章:Python TDD定义Dollar对象相等性

写在前面 这本书是我们老板推荐过的&#xff0c;我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后&#xff0c;我突然思考&#xff0c;对于测试开发工程师来说&#xff0c;什么才更有价值呢&#xff1f;如何让 AI 工具更好地辅助自己写代码&#xff0c;或许…...

nuxt3项目打包部署到服务器后配置端口号和开启https

nuxt3打包后的项目部署相对于一般vite打包的静态文件部署要稍微麻烦一些&#xff0c;还有一个主要的问题是开发环境配置的.env环境变量在打包后部署时获取不到&#xff0c;具体的解决方案可以参考我之前文章 nuxt3项目打包后获取.env设置的环境变量无效的解决办法。 这里使用的…...

MongoDB文档查询

一、实验目的 1. 理解MongoDB文档数据库的基本概念和特性。 2. 掌握在MongoDB中创建集合和插入文档数据的方法。 3. 学习使用MongoDB进行文档查询操作&#xff0c;包括查询、过滤和排序等。 二、实验环境准备 1. JAVA环境准备&#xff1a;确保Java Development Kit (J…...

【GORM】初探gorm模型,字段标签与go案例

GORM是什么&#xff1f; GORM 是一个Go 语言 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它让我们可以使用结构体来操作数据库&#xff0c;而无需编写SQL 语句 GORM 模型与字段标签详解 在 GORM 中&#xff0c;模型是数据库表的抽象表示&#xff0c;字段标签&am…...

Windows下的Milvus安装秘籍:向量数据库轻松上手

目录 一、简介 二、dockers的安装 1.介绍 2.环境准备 1.启动WSL 的功能。 2.安装并启动Hyper-V Windows10下的安装办法&#xff1a; Windows11下的安装办法&#xff1a; 启动Hyper-V 3.Docker的安装 4、验证是否安装成功 三、安装Milvus 1.Milvus下载 2.Milvus启动…...

在GUI中添加一个Label

标签是一种非常简单的小部件,它可以为我们的图形用户界面(GUI)增添价值。它可以阐释其他组件的用途,提供一些额外的信息,这可以引导用户理解输入框组件的含义,也能够解释那些无需用户输入数据的组件所显示数据的含义。 准备就绪 我们将扩展第一个应用案例,即《创建第一…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...