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

【JavaEE】CAS

作者主页:paper jie_博客

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《MySQL》《C语言》《javaSE》《数据结构》等

内容分享:本期将会分享CAS知识.

目录

什么是CAS

CAS怎么实现的

CAS的应用

实现原子类

实现自旋锁

CAS的ABA问题

什么是ABA问题

ABA带来的问题

解决方法


什么是CAS

CAS称为compare and swap,就是比较和交换的意思,它涉及到的操作就是(内存中的原数据为C, 旧的预期值为A, 需要修改的新值为B.):

1. 比较 A 与 C的值是不是一样

2. 如果相等,就会将B的值写入A中

3.返回操作是否成功.

CAS本质上就是一条指令.用来进行比较和交换,而指令本身就具有原子性.基于CAS就给实现线程安全有了一条新的选择. 之前为了线程安全需要加锁,而加锁就可能会造成堵塞.但CAS本身就具有原子性,就不需要加锁,不加锁也就不会造成堵塞.合理的使用CAS也可以解决线程安全的问题.

CAS怎么实现的

简答来说就是:

Java层面的CAS利用的就是unsafe这个类提供的CAS操作.

unsafe的CAS依赖的是JVM针对与不同操作系统实现的Atomic::cmpxchg

Atomic::cmpxchg的实现是使用了汇编的CAS操作,且使用CPU硬件提供的lock机制保证其原子性.

反正就是因为硬件提供了支持,软件层面才能做到.

CAS的应用

实现原子类

标准库中就提供了Java.cutil.concurrent.atomic 包,里面的类都是基于这种方式来实现的. 典型就是Atomiclnteger类,其中的方法getAndIncrement就是相当于i++.

AtomicInteger atomicInteger = new AtomicInteger(0);
// 相当于 i++
atomicInteger.getAndIncrement();

伪代码:

class AtomicInteger {private int value;public int getAndIncrement() {int oldValue = value;while ( CAS(value, oldValue, oldValue+1) != true) {oldValue = value;}return oldValue;
}

假设两个线程都调用到了这个方法.

1.两个线程都读到了value值到oldvalue中.

2. 线程1先执行CAS操作. 因为value和oldvalue一样,就会直接对value赋值.

3其后线程2再执行CAS操作就会发现value和oldvalue不同就会再次将value的值给oldvalue进入循环

4接下来第二次执行CAS,就发现value和oldvalue一样,就会发生赋值.

通过类似于这种方式就可以实现一个原子类.不需要重量级锁也可以高效的完成多线程的自增操作.(这里其实在代码角度不是原子的,但是在硬件上可以让一条指令完成这个操作,也就变成原子的了)

通过这样的代码就可以实现一个原子类.它是不需要使用重量级锁的,这样可以高效的完成多线程的自增操作.

实现自旋锁

我们基于CAS可以实现更加灵活的锁,获取到更多的控制权.

自旋锁伪代码:

这里核心就是使用CAS,当owner不为null时,它就会一直循环判断,当owner为null时,它就会操作成功,将这个线程的地址赋值给owner,结束了可以调用构造方法来将owner置为null,相当于解锁.

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;}}

CAS的ABA问题

什么是ABA问题

我们知道CAS的核心就是比较和交换,判断预期值和内存值是不是一样再交换.但是会有一种情况:

假设有两个线程t1和t2,都需要对一个共享变量num100来进行减50操作. 他们需要进行的步骤:

1. 读取num的值到寄存器中

2.比较看相不相同,相同就修改成50

这时当t1执行到第二步操作时,t2插队进来将这个减50操作完成了,这时num变成了50,后面又有一个t3线程插到t1线程前面,将num的值加50,这时num变成了100.终于轮到t1执行第二步操作时,它发现这个num为100,和寄存器中的值一样,它就会进行-50操作.

这就是ABA现象.

ABA带来的问题

粗略来看,这样是没有什么影响的.但是再一些极端情况下就会产生一些不好的影响. 比如:

小帅今天打算去银行取50块钱.它对ATM机点了一下,发现没反应,就又点了一下.这时ATM机就会产生t1和t2两个相同的-50的线程. 当t1执行到第二步后,t2插队进来执行,将100变成了50.等到t1再执行的时候,它又被插队了,这时小帅的女朋友给它的账户中存了50块钱,账户余额就变成了100.终于等到t1执行时它会发现账户里的值和寄存器中的值一样,于是它的减50操作就成功了.

这就会发生小帅的50块钱不翼而飞的现象.

解决方法

我们可以给需要修改的值引入一个版本号.在比较当前值和预期值时,也要比较版本号相不相同.

1. CAS操作在读取内存值的时候,也需要读取版本号.

2. 在进行比较值的时候,也要比较当前版本号和读取版本号相不相同.相同而修改数据,版本号+1.如果当前版本号大于读取的版本号就表示操作失败了.

举个栗子:
比如小帅取钱.取款机都创建了两个线程,都是执行-50的操作. t1获取到了存款为100,版本号为1.t2获取到了存款为100,版本号为1.

t2扣款成功,存款为50,版本号更新为2.

小帅的女朋友给小帅存了50,存款为100,版本号更新为3.

最终t1执行发现预期值和寄存器值一样,但是当前版本号大于读取版本号,操作失败.

相关文章:

【JavaEE】CAS

作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造&…...

Linux 系统之部署 h5ai 目录列表程序

一、h5ai 介绍 1.1)h5ai 简介 h5ai 是用于 HTTP Web 服务器的现代文件索引器,专注于您的文件。目录以吸引人的方式显示,浏览它们通过不同的视图、面包屑和树概述得到增强。最初 h5ai 是 HTML5 Apache Index 的首字母缩写,但现在它…...

MySQL自增ID耗尽探究:分析与解决方案

MySQL自增ID耗尽探究:分析与解决方案 一、引言 在面试过程中,面试官抛出了一个看似简单却又深入的问题:“MySQL的自增ID用完了,怎么办?” 自增ID耗尽可能看似遥远,但在处理大量数据的系统中,…...

操作系统-操作系统引导(磁盘 操作系统引导过程)

文章目录 总览一个刚买来的磁盘(硬盘)往磁盘安装操作系统后操作系统引导过程例:windows操作系统的初始化程序 总览 一个刚买来的磁盘(硬盘) 此时空空如也 往磁盘安装操作系统后 操作系统在C盘 主引导记录不属于某…...

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖微信小程序端(十三)

地址簿相关功能 1.1 需求分析和设计1.1.1 产品原型1.1.2 接口设计1.1.3 表设计 1.2 代码实现1.2.1 Mapper层1.2.2 Service层1.2.3 Controller层 1.1 需求分析和设计 1.1.1 产品原型 地址簿,指的是消费者用户的地址信息,用户登录成功后可以维护自己的地…...

SAP S/4HANA 2023 Fully-Activated Appliance 虚拟机版介绍

注:市面上所有在售虚拟机均为拷贝本人所作的虚拟机,存在各种技术问题,请知悉。 SAP S4HANA 2023 FAA版本内置了四个Client: 1、000:SAP初始Client,原则上不能动; 2、100:只激活了US…...

【Docker篇】详细讲解容器相关命令

🎊专栏【Docker】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【如愿】 🎄欢迎并且感谢大家指出小吉的问题🥰 文章目录 🛸容器🌹相关命令🍔案例⭐创建并运…...

LSTM学习笔记

上一篇文章中我们提到,CRNN模型中用于预测特征序列上下文的模块为双向LSTM模块,本篇中就来针对该模块的结构和实现做一些理解。 Bidirectional LSTM模块结构如下图所示: 在Pytorch中,已经集成了LSTM模块,定义如下&…...

Android 13.0 Recent列表不显示某个app

1.概述 在13.0 的系统产品rom定制化开发中,在点击导航栏最近任务列表时,如果做到不显示某个app 呢 一种做法是在app中直接处理 一种做法是在framework中处理 接下来看这两种处理方法 1, app中处理 为该应用AndroidManifest xml文件中主MainActivity设置属性 android:exclu…...

速盾网络:高防ip是什么

速盾网络:高防IP是什么 在当今信息化社会中,网络安全问题日益突出,各种网络攻击威胁层出不穷。为了保护企业的网络安全,提高网络业务的稳定性,高防IP应运而生。那么,什么是高防IP呢? 高防IP是…...

全志A133AndroidQ编译方式

编译uboot: cd longan/brandy/brandy-2.0 ./build.sh -p sun50iw10p1 //A133-android-10-plus\longan\brandy\brandy-2.0\u-boot-2018\u-boot.bin复制为u-boot-sun50iw10p1.bin 或者 //longan\brandy\brandy-2.0\u-boot-2018\configs\sun50iw10p1_defconfig cd …...

2024首更---Web Service 教程

Web Services 简介 Web Services 可使您的应用程序成为 Web 应用程序。 Web Services 通过 Web 进行发布、查找和使用。 您应当具备的基础知识 在继续学习之前,您需要对下面的知识有基本的了解: HTMLXML 如果您希望首先学习这些项目,请在…...

Day29- 贪心算法part03

一、K 次取反后最大化的数组和 题目一:1005. K 次取反后最大化的数组和 1005. K 次取反后最大化的数组和 给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组: 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰…...

RPA与ChatGPT的融合:智能化流程的未来

RPA(Robotic Process Automation)是一种利用软件机器人模拟人类操作的技术,可以实现对各种业务流程的自动化执行。ChatGPT是一种基于深度学习的自然语言生成模型,可以根据给定的上下文生成流畅、连贯、有逻辑的文本。RPA与ChatGPT…...

Ubuntu安装maven并且配置阿里源

ubuntu环境搭建专栏🔗点击跳转 Ubuntu系统环境搭建(十二)——Ubuntu安装maven并且配置阿里源 文章目录 Ubuntu系统环境搭建(十二)——Ubuntu安装maven并且配置阿里源1.安装maven1.1更新源列表1.2安装1.3验证 2.配置阿…...

如何通过idea使用JDK8.0创建Spring项目

目前 IDEA 进行了优化,所以我们在创建 Spring 项目时会发现,以及不能选择通过 JDK8.0 创建了,这是因为官方已经不再提供 JDK8.0 创建 Spring 项目,我们可以通过修改创建 Spring 项目的路径来解决该问题 在创建 Spring 项目的页面&…...

Spark读取kafka(流式和批数据)

spark读取kafka(批数据处理) # 按照偏移量读取kafka数据 from pyspark.sql import SparkSessionss SparkSession.builder.getOrCreate()# spark读取kafka options {# 写kafka配置信息# 指定kafka的连接的broker服务节点信息kafka.bootstrap.servers: n…...

经典目标检测YOLO系列(二)YOLOV2的复现(1)总体网络架构及前向推理过程

经典目标检测YOLO系列(二)YOLOV2的复现(1)总体网络架构及前向推理过程 和之前实现的YOLOv1一样,根据《YOLO目标检测》(ISBN:9787115627094)一书,在不脱离YOLOv2的大部分核心理念的前提下,重构一款较新的YOLOv2检测器,来对YOLOV2有…...

怎样使用崭新的硬盘

新买的一块硬盘,接到电脑上,打开机器,却找不到新的硬盘,怎么回事?新的硬盘是坏的么?怎样才能把新硬盘用起来? 可能有几种原因导致您的电脑无法识别新的硬盘。以下是一些建议的解决方法&#xff…...

Kafka-多线程消费及分区设置

目录 一、Kafka是什么?消息系统:Publish/subscribe(发布/订阅者)模式相关术语 二、初步使用1.yml文件配置2.生产者类3.消费者类4.发送消息 三、减少分区数量1.停止业务服务进程2.停止kafka服务进程3.重新启动kafka服务4.重新启动业…...

计算机导论06-人机交互

文章目录 人机交互基础人机交互概述人机交互及其发展人机交互方式人机界面 新型人机交互技术显示屏技术跟踪与识别(技术)脑-机接口 多媒体技术多媒体技术基础多媒体的概念多媒体技术及其特性多媒体技术的应用多媒体技术发展趋势 多媒体应用技术文字&…...

hot100:07接雨水

题目链接: 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 算法思想: 这里采取的是暴力解法和双指针的解法,但是这个题目还有其他的两种解法(单调栈和动态规划,同学可以自行了解&#xff…...

Docker安装MySQL教程分享(附MySQL基础入门教程)

docker安装MySQL Docker可以通过以下命令来安装MySQL容器: 首先确保已经在计算机上安装了Docker。如果没有安装,请根据操作系统的不同进行相应的安装。 打开终端或命令提示符,并运行以下命令拉取最新版本的MySQL镜像: docker pu…...

麒麟V10挂载iso,配置yum源

本文介绍yum 如何挂载本地镜像源 1) 拷贝镜像到本地 2) 执行以下命令: # mount -o loop 镜像路径及镜像名字 /mnt(或 media) 挂载前 挂载后 3) 进入/etc/yum.repos.d(yum.repos.d 是一个目录,该目录是分析 RPM 软件…...

《Linux C编程实战》笔记:信号的捕捉和处理

Linux系统中对信号的处理主要由signal和sigaction函数来完成&#xff0c;另外还会介绍一个函数pause&#xff0c;它可以用来响应任何信号&#xff0c;不过不做任何处理 signal函数 #include <signal.h> void (*signal(int signum, void (*handler)(int)))(int);可以分解…...

python算法与数据结构---单调栈与实践

单调栈 单调栈是一个栈&#xff0c;里面的元素的大小按照它们所在栈的位置&#xff0c;满足一定的单调性&#xff1b; 性质&#xff1a; 单调递减栈能找到左边第一个比当前元素大的元素&#xff1b;单调递增栈能找到左边第一个比当前元素小的元素&#xff1b; 应用场景 一般用…...

文心一言使用分享

ChatGPT 和文心一言哪个更好用&#xff1f; 一个直接可以用&#xff0c;一个还需要借助一些工具&#xff0c;还有可能账号会消失…… 没有可比性。 通用大模型用于特定功能的时候需要一些引导技巧。 import math import time def calculate_coordinate(c, d, e, f, g, h,…...

【C++干货铺】C++11新特性——lambda表达式 | 包装器

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 C98中的排序 lambda表达式 lambda表达式语法 表达式中的各部分说明 lambda表达式的使用 基本的使用 [var]值传递捕捉变量var ​编辑 [&var]引用传递捕…...

在 EggJS 中实现 Redis 上锁

配置环境 下载 Redis Windows 访问 https://github.com/microsoftarchive/redis/releases 选择版本进行下载 - 勾选 [配置到环境变量] - 无脑下一步并安装 命令行执行&#xff1a;redis-cli -v 查看已安装的 Redis 版本&#xff0c;能成功查看就表示安装成功啦~ Mac brew i…...

Unity-场景

创建场景 创建新的场景后&#xff1a; 文件 -> 生成设置 -> Build中的场景 -> 将项目中需要使用的场景拖进去 SceneTest public class SceneTest : MonoBehaviour {// Start is called before the first frame updatevoid Start(){// 两个类&#xff1a; 场景类、场…...