【JavaEE】CAS

news2024/11/20 13:30:25

作者主页:paper jie_博客

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

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

其他专栏:《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执行发现预期值和寄存器值一样,但是当前版本号大于读取版本号,操作失败.

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

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

相关文章

工会排队:零撸式消费新体验,引爆市场热度

随着消费市场的日益竞争,消费者对于购物体验的要求也越来越高。传统的促销方式已经无法满足消费者的需求,于是,一种全新的消费模式——工会排队应运而生。这种创新的消费模式,让消费者在购物的同时,还能获得实实在在的…

Python自动化带来工资翻倍,一个小伙伴的成功之路

今年的行情大家都有所了解,各大五百强带头裁员优化,不少测试同行每天都在为保住工作而发愁。有的投简历石沉大海,甚至连面试机会都没有。 但是今天,我要给大家分享一个令人振奋的故事。关于一个工作不满3年的小伙伴,在…

测评自养号:如何通过销量数据优化阿里国际、eBay产品策略

作为全球顶级的跨境电商平台,阿里国际和eBay已经吸引了数以万计的跨境电商商家进驻。对于这些商家而言,持续关注自己店铺内产品的销售动态是至关重要的,这不仅能够帮助他们更好地了解店铺的经营状况,还能及时发现并解决潜在问题&a…

街机模拟游戏逆向工程(HACKROM)教程:[4]MAME的作弊功能

需要对游戏进行逆向分析,我们首先需要了解游戏的内存系统。在一个游戏的运行过程中,游戏中所有的变动,比如玩家的血量,敌人的血量,玩家所在位置,场景的位置,剩余时间,等等一切&#…

如何制作一本电子版时尚杂志

​随着数字媒体的崛起,电子版时尚杂志已成为一种新的时尚风向标。然而,如何制作一本独具特色的电子版时尚杂志,却让许多初涉此领域的品牌和设计师感到困惑。教你一些方法,制作一本电子版时尚杂志。 一、明确目标与定位 首先&…

10.云原生之在线开发调试

云原生专栏大纲 文章目录 vscode-server介绍VSCode Server 和云开发结合vscode-server安装code-server安装插件在线安装插件离线安装插件安装中文插件 配置开发环境在容器中安装开放环境Dockerfile制作镜像 git拉取项目 vscode-server介绍 VSCode Server(Visual S…

建造者模式深入理解:演示建造单个和多个产品的实践,结合模板模式,通俗易懂

首先呢看下建造者的定义是什么样的,先读一遍 建造者模式 建造者模式(Builder Pattern)是一种创建型设计模式,它主要用于将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表现形式。这种模式…

如何用Mac工具制作“苹果高管形象照”

大伙儿最近有没有刷到“苹果高管形象照”风格,详细说来就是: 以苹果官网管理层简介页面中,各位高管形象照为模型,佐以磨皮、美白、高光等修图术,打造的看上去既有事业又有时间有氧的证件照,又称“苹…

【教学类-43-21】完结篇 16宫格(4*4可算全部数字)

作品展示: 16宫格里面的4*4小格子可以凑满1-16,旁边的7宫格格2份 背景需求: 做完了1-20宫格的A4模板,最后做一个16宫格小格子(附加7宫格2套)的样式,只有4宫格(2*2)、9宫…

uniapp+vue3打包问题记录

**背景:**打包app出现问题,只显示底部导航的文字,其他一片空白 1. pages.json文件:tabBar中的iconPath图标格式不支持svg,只支持:png, jpg, jpeg的格式,当图片改为.png的时候可以正常显示 2. …

代码随想录算法训练营第6天 | 242.有效的字母异位词 , 349. 两个数组的交集 , 202. 快乐数 , 1. 两数之和

哈希知识基础 文章链接:https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E5%93%88%E5%B8%8C%E8%A1%A8 242.有效的字母异位词 题目链接:https://leetcode.cn/problems/valid-anagram/description/…

cv 不能正常读取中文路径

之前一直以为是PyQT的getOpenFileNames方法不能读取中文路径的。多次尝试后发现不是,是OpenCV的问题。 self.selected_imgPaths, _ QtWidgets.QFileDialog.getOpenFileNames(self, "打开图片", "./pending_images", "*.jpg;;*.JPG;;*.png…

C语言——实用调试技巧

一、为什么漏洞叫bug 为什么漏洞的英文是bug,众所周知bug有虫子的意思,这其实有一个很有名的故事。 1947年,计算机科学的先驱格蕾丝霍普(Grace Hopper)和她的团队在使用哈佛大学的马克二电脑时,发现了一个…

为CT_P自动注册与CT_Run相关的方法

概述 在docx.oxml.text.paragraph模块中定义了CT_P段落对象元素类,但是CT_P中并未定义add_r等与CT_Run相关的方法。在不断探索源码逻辑的过程中,对这种自动为类注册合适的方法的功能进行了梳理——xmlchemy这个模块设计的真好!!&…

rust跟我学(一):模块编写与使用

在rust中,单元文件可以被称为模块。 以下内容,将以get_local_info为例,讲解mod在工程中的使用。 先看下图,network.rs是src文件夹里的一个文件,我们可以单独把这个文件理解成一个模块。Rust比较智能,它可以将文件名称直接理解成一个模块,这在go里面是做不到的。 Rust其实…

​​社交媒体与新闻:Facebook在信息传播中的作用

社交媒体已经成为我们获取和传播新闻的主要渠道之一,而Facebook作为社交媒体的巨头,在信息传播中扮演着举足轻重的角色。本文将深入探讨社交媒体对新闻传播的影响,聚焦于Facebook在这一领域的独特作用,以及这种作用对我们的新闻体…

2024北京智博会:共赴科技盛会,助力跨界融合与实体经济深度发展

2024年6月,一场备受瞩目的科技盛会将在北京亦创国际会展中心拉开帷幕。作为国内外科技交流的重要平台,2024北京智博会将汇集众多科技领域的精英和企业,共同探讨跨界应用、实体经济深度融合等议题,为推动科技强国发展注入新动力。 …

SSL之mkcert构建本地自签名

文章目录 1. 什么是SSL2. mkcert:快速生成自签名证书2.1 mkcert的工作流程如下:2.2 window 本地实现自签证书2.2.1 下载安装2.2.2 下载,生成本地 SSL2.2.3 生成 pem 自签证书,可供局域网内使用其他主机访问。2.2.4 使用-psck12 生成*.p12 文件 2.3 Sprin…

7.11、Kali Linux中文版虚拟机安装运行教程

目录 一、资源下载准备工作 二、安装教程 三、kali linux换源 四、apt-get update 报错 一、资源下载准备工作 linux 中文版镜像历史版本下载:http://old.kali.org/kali-images/ 大家可以自行选择版本下载,本人下载的是2021版本 二、安装教程 打开vmvare wokst…

修炼九阳神功——“函数”

目录 前言 1. 函数的概念 2. 库函数 2.1 标准库和头⽂件 2.2 库函数的使用方法 2.2.1 功能 2.2.2 头⽂件包含 2.2.3 实践 2.2.4 库函数⽂档的⼀般格式 3. 自定义函数 3.1 函数的语法形式 3.2 函数的举例 ​编辑 4. 形参和实参 4.1 实参 4.2 形参 4.3 实参和形…