每日一博 - CAS(Compare-And-Swap)原理剖析

简介: 每日一博 - CAS(Compare-And-Swap)原理剖析

d0fdb2e70e1847b2b9749789048967d3.png

What’s CAS & sun.misc.Unsafe


全称 Compare-And-Swap , 主要实现的功能是和内存中的某个位置的值进行比较判断是否为预期值,如果是预期值则更改为新值, 整个过程具有原子性。



9b047aa44934416ba5414096d0d1e737.png


CAS & sun.misc.Unsafe


CAS属于CPU并发原语


CAS是一种系统原语,原语属于操作系统应用范畴,是由若干条指令组成,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致的问题,即CAS是线程安全的


在JDK中,主要体现在sun.misc.Unsafe类。

9eb7a6c8a71649c09a18f43f9b561b2a.png


当执行UnSafe类中的cas相关方法时, JVM会转换成类似汇编指令,通过它实现了原子操作。

来看个代码

package com.artisan.juc;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2021/11/6 13:11
 * @mark: show me the code , change the world
 */
public class CASTest {
    public static void main(String[] args) {
        // 设置初始值为100
        AtomicInteger atomicInteger = new AtomicInteger(100);
        // 使用atomicInteger的compareAndSet,如果为100,则更新为123
        boolean b = atomicInteger.compareAndSet(100, 123);
        System.out.println(b + "----" + atomicInteger.get());
        // 使用atomicInteger的compareAndSet,如果为100,则更新为456 (上一步已经更新成了123,所以不是100)
        b = atomicInteger.compareAndSet(100, 456);
        System.out.println(b + "----" + atomicInteger.get());
    }
}

c59038c92be04915a36746334093b944.png


输出

true----123
false----123



4412520df1c442d88a7646ed1f8208c0.png



以AtomicInteger为例底层原理剖析


继续在上个例子的基础上,完善一下,方便引入知识点,增加红框内如下代码:

6a90ff9047c44082bbb90ef8a9b569b5.png

输出

06f58b5a277f4786add60b5e9fb005ef.png


我们来分析下 getAndIncrement

先看看 AtomicInteger类


6c449b0a091547c9857a365f80b73bf7.png23d300c1c6ad43f6b6491964e96a9397.png


看方法的注释说明: 以原子的方式在当前值的基础上加1 ,返回的是加1之前的值。

可以看到其实是调用了unsafe# getAndAddInt

那先看看Unsafe类 呗



da56f03634f0484fa3cddf7b64585005.png


内部方法操作可以像C的指针一样直接操作内存


Unsafe位于sun.misc包中,该类的方法都是native的本地方法 ,这也意味着unsafe类中的方法都直接调用操作系统底层资源执行相应的任务。


Unsafe类是CAS的核心类. 我们知道Java无法直接访问底层操作系统,需要通过native方法来实现。 Unsafe这个魔法类可以理解为一个后门,通过该类可以直接操作特定的内存数据。


继续【getAndAddInt方法 】


d2f3d7a6f48849f4872281839ae573ac.png



07d493df19524528826551540b2c0076.png


b05fb42fdffd425dad4c337b292c9729.png


var1: AtomicInteger本对象


var2: 该对象值得引用地址


var4: 需要变动的数量


var5: var5 = this.getIntVolatile(var1, var2); 从主内存中拿到的值 , 如果当前值和期望值一样,就执行 var5 + var4 . (用var1和var2找到的内存中的真实值用该对象当前的值与var5比较)


do while 循环 , 如果compareAndSwapInt返回false,那么就一直执行 while方法,直到期望的值和真实值一样


a911f6e5685240dfb56f016643d83377.png

CAS有3个操作数,内存值V,旧的预期值,要修改的更新值。当且仅当预期值和内存值相同时,将内存值修改为更新值,否则不操作 .


CAS缺点


CAS不加锁,保证一致性,但是需要多次比较


对于多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候只能用锁来保证原子性


循环时间长,开销大(因为执行的是do while,如果比较不成功一直在循环,最差的情况,就是某个线程一直取到的值和预期值都不一样,这样就会无限循环)


只能保证一个共享变量的原子操作,当对一个共享变量执行操作时,我们可以通过循环CAS的方式来保证原子操作


ABA 问题


如果一个变量初次读取的时候是 A 值,它的值被改成了 B,后来又被改回为 A,那 CAS 操作就会误认为它从来没有被改变过。

相关文章
|
6月前
|
缓存 算法 安全
CAS机制(Compare And Swap)源码解读与三大问题
CAS机制(Compare And Swap)源码解读与三大问题
|
23天前
|
算法 Java
介绍一下CAS算法的实现原理
【10月更文挑战第20天】介绍一下CAS算法的实现原理
11 0
|
6月前
|
安全 Java 程序员
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
62 0
|
安全 算法 Java
CAS是"Compare and Swap"(比较并交换)
CAS是"Compare and Swap"(比较并交换)的缩写,是一种多线程同步的原子操作。它基于硬件的原子性保证,用于解决并发环境下的数据竞争和线程安全问题。
104 0
|
6月前
|
安全 Java 程序员
【JavaEE】CAS(Compare And Swap)操作
【JavaEE】CAS(Compare And Swap)操作
|
6月前
|
存储 缓存 安全
Buffer循环机制
Buffer循环机制
58 0
|
Java 调度 C语言
【JavaEE】CAS机制(比较并交换)
哈喽,大家好~我是你们的老朋友保护小周ღ,本期为大家带来的是 CAS (compare and swap) 比较并交换,CAS 是物理层次支持程序的原子操作,CAS 是一种完全不同于 synchronized 锁保证多线程安全问题的机制,可以用来进行无锁编程,讲述了 CAS 的概率,使用场景,以及优缺点,确定不来看看嘛~ 更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★* ‘
129 0
|
安全 算法 Java
CAS之比较并交换
CAS之比较并交换
CAS之比较并交换
十一、Belady现象和LRU、FIFO、clock的比较
十一、Belady现象和LRU、FIFO、clock的比较
|
Java API
java并发原理实战(3) -- 线程的中断和初始化
java并发原理实战(3) -- 线程的中断和初始化
230 0
java并发原理实战(3) -- 线程的中断和初始化