Java并发编程CAS

CAS、CAS自旋、CAS自旋锁、CLH锁与Java AQS:深入理解并发编程核心机制 CAS(Compare and Swap)是一种无锁(Lock-Free)的原子操作,用于在多线程环境下实现数据同步。CLH(Craig, Landin, Hagersten)锁是一种基于链表的队列锁,通过隐式队列管理线程,减少缓存一致性流量。基于CAS自旋实现的锁,线程在获取锁失败时不会阻塞,而是循环尝试。理解这些机制的原理与实现,是编写高效、健壮并发代码的关键。CAS自旋是指线程在CAS失败后循环重试,直到成功。)的核心框架,用于构建锁和同步器(如。AQS提供需子类实现的抽象方法(如。 阅读详情

CAS 是什么

CAS 的全称 Compare-And-Swap,它是一条 CPU 并发。

它的功能是判断内存某一个位置的值是否为预期,如果是则更改这个值,这个过程就是原子的。

CAS 并发原体现在 JAVA 语言中就是 sun.misc.Unsafe 类中的各个方法。调用 UnSafe 类中的 CAS 方法,JVM 会帮我们实现出 CAS 汇编指令。这是一种完全依赖硬件的功能,通过它实现了原子操作。由于 CAS 是一种系统源语,源语属于操作系统用语范畴,是由若干条指令组成,用于完成某一个功能的过程,并且原语的执行必须是连续的,在执行的过程中不允许被中断,也就是说 CAS 是一条原子指令,不会造成所谓的数据不一致的问题。

比较并交换

CAS的意思就是比较并交换。上面说到,这个比较过程是原子的。我们新建一个测试类。

public class CASDemo {
    public static void main(String[] args) {
       checkCAS();
    }

    public static void checkCAS(){
        AtomicInteger atomicInteger = new AtomicInteger(5);
        System.out.println(atomicInteger.compareAndSet(5, 2019) + "\t current data is 
        " + atomicInteger.get());
        System.out.println(atomicInteger.compareAndSet(5, 2020) + "\t current data is 
        " + atomicInteger.get());
    }
    atomicInteger.getAndIncrement();
    System.out.println("current data is " + atomicInteger.get());
}

查看返回结果

true	 current data is 2019
false	 current data is 2019
current data is 2020

原子整型类的初始值是5,当第一次调用compareAndSet的时候期望值是5,更新值是2019,此时的期望值和atomicInteger 值相等,则替换为更新值,输出为2019;第二次调用compareAndSet的时候期望值还是5,此时atomicInteger的值已经更新为2019,期望值和原始值不想等,不做更新操作,所以此时的atomicInteger值还是2019。

compareAndSet是AtomicInteger的一个方法

/**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

他调用的是unsafe类的compareAndSwapInt方法,this表示当前值对象,valueOffset是当前对象在内存中的偏移量,expect为期望值,update为更新值。

原子性

需要说到 atomicInteger.getAndIncrement();这个方法,类似于i++。

    /**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

也是调用的unsafe类的方法。
来看一下getAndAddInt:

    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

var1为当前对象,var2为当前对象在内存中的偏移量,var4为1,var5为getIntVolatile(var1, var2)的返回值,getIntVolatile方法的意思是当前对象var1且内存偏移量为var2时的值是多少。

在while循环中,同样调用了compareAndSwapInt方法,此时的var5为期望值,var5+var4为更新值。直到比较成功。

Unsafe类

unsafe类是CAS的核心类,由于java无法直接访问底层系统,需要通过本地(native)方法来访问,基于unsafe类可直接操作特定内存的数据unsafe类存在于sun.mics包中,其内部方法可以像c的指针一样直接操作内存。因为 Java 中 CAS 操作执行依赖于 Unsafe 类。

变量 vauleOffset,表示该变量值在内存中的偏移量,因为 Unsafe 就是根据内存偏移量来获取数据的。

变量 value 用 volatile 修饰,保证了多线程之间的内存可见性。

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            // 获取下面 value 的地址偏移量
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value;
	// ...
}

CAS 的缺点

  • 循环时间长开销很大
    • 如果 CAS 失败,会一直尝试,如果 CAS 长时间一直不成功,可能会给 CPU 带来很大的开销(比如线程数很多,每次比较都是失败,就会一直循环),所以希望是线程数比较小的场景。
  • 只能保证一个共享变量的原子操作
    • 对于多个共享变量操作时,循环 CAS 就无法保证操作的原子性。
  • 引出 ABA 问题

ABA 问题

原子引用

public class AtomicRefrenceDemo {
    public static void main(String[] args) {
        User z3 = new User("张三", 22);
        User l4 = new User("李四", 23);
        AtomicReference<User> atomicReference = new AtomicReference<>();
        atomicReference.set(z3);
        System.out.println(atomicReference.compareAndSet(z3, l4) + "\t" + atomicReference.get().toString());
        System.out.println(atomicReference.compareAndSet(z3, l4) + "\t" + atomicReference.get().toString());
    }
}

@Getter
@ToString
@AllArgsConstructor
class User {
    String userName;
    int age;
}

ABA 问题是怎么产生的

public class ABADemo {
    private static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);

    public static void main(String[] args) {
        new Thread(() -> {
            atomicReference.compareAndSet(100, 101);
            atomicReference.compareAndSet(101, 100);
        }).start();

        new Thread(() -> {
            // 保证上面线程先执行
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicReference.compareAndSet(100, 2019);
            System.out.println(atomicReference.get()); // 2019
        }).start();
    }
}

当有一个值从 A 改为 B 又改为 A,这就是 ABA 问题。

ABA 问题解决

时间戳原子引用

public class ABADemo2 {
    private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);

    public static void main(String[] args) {
        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + " 的版本号为:" + stamp);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1 );
            atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1 );
        }).start();

        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + " 的版本号为:" + stamp);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean b = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp + 1);
            System.out.println(b); // false
            System.out.println(atomicStampedReference.getReference()); // 100
        }).start();
    }
}

输出结果

Thread-0 的版本号为:1
Thread-1 的版本号为:1
false
100

个人博客
腾讯云社区
掘金
优快云
简书
GitHub
码云
OSCHINA
Segmentfault
公众号:wx.jpg

Java 的并发编程模型:从 synchronized 到 CAS 和CAS是Java并发编程模型中两种重要的机制。简单易用,能够保证线程安全,但在高并发场景下性能较低。CAS通过无锁的方式实现了高效的并发控制,但在某些情况下可能出现ABA问题。在实际开发中,我们需要根据具体的应用场景选择合适的并发控制机制,以提高程序的性能和可靠性。 阅读详情

相关推荐

利用Sigrity的SPEED2000进行时域电源噪声分析

SPEED2000进行时域电源噪声分析

ZHENGSA的博客 3620

java并发之CAS

一、什么是CAS CAS,全称为CompareAndSwap,即比较并交换。 二、代码 CAS实现一个自旋锁 import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; public class SpinLockDemo { public AtomicReference<Thread> atomicThread = new AtomicReference<

万物皆可互联,一切均可编程 297

三相SVPWM逆变器双闭环PI解耦控制:从dq坐标系到参数整定实战

本文深入解析了三相SVPWM逆变器的双闭环PI解耦控制技术。通过引入dq坐标系,将交流量转换为直流量,并结合前馈补偿实现电流环的解耦控制。文章详细阐述了从数学模型推导、控制器设计到参数整定与SVPWM实现的完整流程,为工程师提供了从理论到实战的系统性指导。

weixin_28292761的博客 404

Java并发编程-CAS

CAS 的基本思路就是,如果这个地址上的值和期望的值相等,则给其赋予新值,否则不做任何事儿。循环 CAS 就是在一个循环里不断的做 比较且交换( Compare And Swap) 操作,直到成功为止。

千月落 9051

数据库和BI工程师面试题

 一.数据库 1.Oracle数据库,视图与表的区别?普通视图与物化视图的区别?物化视图的作用? 2.Oracle数据库,有哪几类索引,分别有什么特点? 3.Union与Union All的区别? 4.对游标的理解?游标的分类?使用方法? 5.如何查找和删除表中的重复数据?给出方法或SQL。 6.不借助第三方工具,怎么查看SQL的执行计划? 7.创建索引有哪些需要注意的要点?

web_go_run的专栏 1万+

LIGGGHTS颗粒模拟入门:从DEM原理到工程实践

离散元法(DEM)是一种用于模拟颗粒物质行为的数值方法,其核心原理是通过计算每个颗粒的运动和相互作用来预测颗粒系统的宏观行为。该方法基于牛顿第二定律和接触力学模型,能够精确描述颗粒间的碰撞、摩擦和粘结等微观机制。在工程实践中,DEM技术为优化工业设备设计、预测材料流动和减少实验成本提供了重要价值。它广泛应用于制药造粒、矿石破碎、粉体输送和农业加工等领域,帮助工程师和研究人员深入理解颗粒系统的复杂动力学。LIGGGHTS作为一款基于LAMMPS的开源DEM软件,继承了其高效的并行计算架构,并针对颗粒模拟进行了

weixin_33979203的博客 419

JAVA并发编程: CAS和AQS

说起JAVA并发编程,就不得不聊聊CAS(Compare And Swap)和AQS了(AbstractQueuedSynchronizer)。 CAS(Compare And Swap) 什么是CAS CAS(Compare And Swap),即比较并交换。是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新

Vioao's Blog 4万+

2025.06.20【pacbio】|PB甲基化分析结果的统计与可视化介绍

本文介绍了PacBio甲基化数据的统计分析与可视化方法。主要内容包括:1) 分析甲基化位点分布、比例及染色体分布;2) 修饰基序(Motif)的统计与热图展示;3) 全基因组和局部区域测序深度可视化;4) 使用IGV查看单个reads修饰情况。文章提供了R代码示例,涵盖柱状图、分布图、热图等多种可视化形式,并建议了差异甲基化分析等进阶方法,帮助科研人员深入挖掘甲基化数据。

2066

Java CAS并发编程解析

在当今的互联网时代,高并发应用的开发已经成为一项基本技能。以一个在线购物平台为例,当用户在高峰时段进行购物时,系统可能会面临大量的并发请求。在这样的场景下,如果数据更新操作没有妥善处理,就很容易出现数据不一致的问题。为了解决这个问题,我们需要介绍Java高并发知识点之Compare-And-Swap(CAS)。在多线程环境中,当多个线程尝试同时修改同一数据时,传统的锁机制可能会导致性能瓶颈。

我是Java程序员廖志伟,感谢朋友们的支持!不定期贡献一篇高品质、过万文字、图文并茂且附有视频解说、满载代码示例注释的良心之作,坚决杜绝粗制乱造。 829

【100%通过率】华为od机试C卷【特殊的加密算法】Python 实现

有一种特殊的加密算法,明文为一段数字串,经过密码本查找转换,生成另一段密文数字串。规则如下1.明文为一段数字串由0-9组成2.密码本为数字0-9组成的二维数组3.需要按明文串的数字顺序在密码本里找到同样的数字串,密码本里的数字串是由相邻的单元格数字组成,上下和左右是相邻的,注意:对角线不相邻,同一个单元格的数字不能重复使用。

MISAYAONE的博客 5924

华为OD机试双机位C卷-组装新的数组(Py/Java/C/C++/Js/Go)

华为OD机试(机考)双机位C卷 【组装新的数组】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试 - 组装新的数组。

qq_45776114的博客 1145

java cas求和_Java并发编程之CAS

在Java并发编程的世界里,synchronized 和 Lock 是控制多线程并发环境下对共享资源同步访问的两大手段。其中 Lock 是 JDK 层面的锁机制,是轻量级锁,底层使用大量的自旋+CAS操作实现的。那什么是CAS呢?CAS,compare and swap,即比较并交换,什么是比较并交换呢?在Lock锁的理念中,采用的是一种乐观锁的形式,即多线程去修改共享资源时,不是在修改之前就加锁...

weixin_29346059的博客 117

AUTOSAR进阶图解==>AUTOSAR_SWS_COM

AUTOSAR COM模块是AUTOSAR通信堆栈的核心组件,提供信号导向的通信服务。该模块位于通信服务层,连接RTE与PDU Router,主要功能包括信号封装/提取、传输模式管理、信号路由、超时监控和字节序转换等。COM模块架构分为应用层、通信服务层和通信抽象层,包含信号管理、I-PDU处理、传输模式管理等组件。其配置结构包括顶层容器、I-PDU组、I-PDU和信号等多层次配置对象,支持丰富的参数设置。模块采用严格的状态管理机制,包括模块状态和I-PDU组状态转换,确保通信可靠性。

一名留德华的,康德的信徒的,专注于汽车电子领域的博客 1244

Java并发编程之CAS

在进行Java并发编程的时候,我们都会使用到锁来控制并发线程对临界资源的安全访问。用的最多的就是synchronized,但是synchronized属于重量级锁、悲观锁,在很多时候会引起性能问题。除了synchronized还有cas,cas属于乐观锁,在一定的场景下会比synchronized更高效。java.util.concurrent包下的ReentrantLock内部的AQS,还...

码行天下 251

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

java并发编程 Atomic、CAS和AQS的介绍

/ 自定义信号量类 class CustomSemaphore {// 构造函数,初始化信号量许可数量 public CustomSemaphore(int permits) {} // 获取许可 public void acquire() throws InterruptedException {} // 释放许可 public void release() {

不知道说什么的博客 1101

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

java cas并发_Java并发编程之CAS

在Java并发编程的世界里,synchronized 和 Lock 是控制多线程并发环境下对共享资源同步访问的两大手段。其中 Lock 是 JDK 层面的锁机制,是轻量级锁,底层使用大量的自旋+CAS操作实现的。学习并发推荐《Java并发编程的艺术》那什么是CAS呢?CAS,compare and swap,即比较并交换,什么是比较并交换呢?在Lock锁的理念中,采用的是一种乐观锁的形式,即多线程...

weixin_33694136的博客 114

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Java并发编程之CAS第一篇理解

Java并发编程之CAS第一篇-什么是CAS 通过前面几篇的学习,我们对并发编程两个高频知识点了解了其中的一个—volatitl。从这一篇文章开始,我们将要学习另一个知识点—CAS.本篇是《凯哥并发编程学习》系列之《CAS系列》教程的第一篇:什么是CAS。 本文主要内容: 生活中举例;CAS定义;CAS代码演示。 一:生活中的例子 在电影《智取威虎山》中,杨子荣进入威虎山的时候,土匪说:天王盖地虎,杨子荣对:宝塔镇河妖。类似这样的黑话,几个土匪和杨子荣对过之后,座山雕,三爷才发话:这么说,你是徐旅

115

Java并发编程:CAS操作

CAS(Compare-and-Swap)是一种原子操作,用于在多线程环境中实现无锁同步。它通过比较内存地址的当前值与预期值,如果匹配则更新为新值,否则不执行操作。CAS的优势在于减少锁的使用,提升并发性能,但其局限性包括只能操作单一内存地址、设计复杂、可能引发ABA问题。ABA问题发生在变量值经历A->B->A变化时,导致冲突检查失效。为解决ABA问题,可以使用带有版本戳的原子引用类,如AtomicStampedReference,但这会增加存储和性能开销。

qj19842011的专栏 822

Java并发编程 - CAS 底层剖析

Java并发编程 - CAS 底层剖析 由volatile关键字可知,他可以保证JMM内存模型的可见性和有序性(禁止指令重排序)但是不能保证原子性,导致线程安全问题,我们可以加synchronized关键字来解决但是对于有些业务来说,synchronized太重了开销太大,所以我们可以用JUC包下的原子操作系列Atomic操作类,提供了操作的原子性。在底层的实现原理还是CAS。 CAS:...

J-Proton博客 371

Java 并发编程的 CAS(Compare and Swap)是什么?

并发库的“心脏”。

qq_74825504的博客 1049

Java并发编程之CAS算法

前言 在谈CAS算法时,我们先来了解一下无锁的概念。 无锁分为以下两大派系: 对于乐观派系而言,它们认为事情总会往好的方向去发展,总是认为坏的情况发生概率特别小,可以无所顾忌的做任何事情; 对于悲观派系而言,它们总会认为发展事态如果不及时控制,以后就无法挽回,即时此种局面不会发生的情况下。 上述两大派系映射到并发编程中就如同加锁与无锁策略,即加锁是一种悲观策略,无锁是一种乐观策略,因为对于加锁...

q309572960的博客 224

java cas求和_java并发编程之cas详解

CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术。简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值。这听起来可能有一点复杂但是实际上你理解之后发现很简单,接下来,让我们跟深入的了解一下这项技术。CAS的使用场景在程序和算法中一个经常出现的模式就是“check and act”模式。先...

weixin_39609670的博客 126

【java并发编程】cas乐观锁

一、cas是什么? cas全程Compare and swap,比较并交换。一种无锁原子算法,是一种乐观锁,用于原子性的更新变量。 二、cas实现原理 CAS靠硬件实现,是一条CPU的原子指令,基于汇编指令cmpxchg(Intel x86)实现,其作用是让CPU先比较两个值是否相等,然后原子性地更新某个内存地址的值。 三、cas操作在java使用 unsafe类中的compareAndSwapInt方法 是经典实现 进入native方法,在c++源码unsafe.cpp文件中

sumengnan的博客 984

java cas机制_java并发编程中的CAS机制,你理解嘛?

学习Java并发编程,CAS机制都是一个不得不掌握的知识点。这篇文章主要是从出现的原因再到原理进行一个解析。希望对你有所帮助。一、为什么需要CAS机制?为什么需要CAS机制呢?我们先从一个错误现象谈起。我们经常使用volatile关键字修饰某一个变量,表明这个变量是全局共享的一个变量,同时具有了可见性和有序性。但是却没有原子性。比如说一个常见的操作a++。这个操作其实可以细分成三个步骤:(1)从内...

weixin_36138385的博客 289
上一篇: 模糊查询%在最前面,能否或者怎么使用索引
下一篇: JVM&GC(一)java引用
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值