• JUC03-volatile、CAS及并发原子类


    一、 Volatile

    Volatile可以用来修饰成员变量和静态成员变量,保证可见性、有序性

    可见性:保证volatile修饰的变量每次读取都会从主从中进行读取而不是cpu缓存
    有序性:对Volatile修饰变量进行写操作时,会在该操作后加上写屏障,进行读操作时会在读操作前加上读屏障。

    读写屏障

    写屏障(sfence)保证在该屏障之前的,对共享变量的改动,都同步到主存当中,并且会确保指令重排序时,禁止屏障前后的写操作跨越屏障。

    读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据。并且会确保指令重排序时,禁止屏障前后的读操作跨越屏障

    重排序

    在这里插入图片描述

    二、CAS

    cas是compareAndSet的缩写,底层使用cpu指令,是一个比较并赋值的原子操作

    结合 CAS 和 volatile 可以实现无锁并发,适用于线程数少、多核 CPU 的场景下。

    • CAS 是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃亏点再重试呗。
    • synchronized 是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量,我上了锁你们都别想改,我改完了解开锁,你们才有机会。

    CAS 体现的是无锁并发、无阻塞并发,请仔细体会这两句话的意思
    因为没有使用 synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一
    但如果竞争激烈,可以想到重试必然频繁发生,反而效率会受影响

    相比于

    三、 原子累加器LongAdder

    与之前提到的AtomicInteger不同,LongAdder 累加器采取了效率更高的方法应对高并发情况对数据的累加需求

    优化一:多个cell分摊并发压力

    LongAdder 关键字段

    // 累加单元数组, 懒惰初始化
    transient volatile Cell[] cells;
    // 基础值, 如果没有竞争, 则用 cas 累加这个域
    transient volatile long base;
    // 在 cells 创建或扩容时, 置为 1, 表示加锁
    transient volatile int cellsBusy;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    当执行add(x)操作时大概执行流程如下:

    1. 判断当前是否发生过竞争

      • 若没有则使用cas对base进行累加
    2. 若有则判断当前线程是否有对应cell

      • 有则使用cas对该cell进行累加
    3. 若没有或者对base的cas累加失败或者对cell的cas累加失败

    4. 创建新的cell进行累加(具体创建与否需要根据机器cpu的核心数量)

    5. 将所有cell的值进行求和返回

    优化二:缓存行伪共享

    不同CPU的寄存器中用到了不同的变量,一个用到的是X,一个用到的是Y,并且XY在同一个缓存行中,这就叫做缓存行伪共享

    所谓缓存行就是cpu缓存的单位,每个缓存行大小为64个字节。当对缓存行中一个数据进行修改时,整个缓存行都将失效
    在这里插入图片描述
    LongAdder内部维护一个cells数组,包含多个cell(累加单元),每个cell绑定一或多个线程来分摊并发压力,然而,即使不同的cell对应不同的线程,但伪共享的出现会导致线程1对一个cell的修改导致另一个cell的值失效,需要重新从内存读取,大大影响其性能
    在这里插入图片描述

    @Contended注解填充缓存行解决伪共享

    此注解可以填充被修饰的对象,使一个缓存行最多只能存储一个该对象,解决伪共享问题
    在这里插入图片描述

    总结

    LongAdder通过使用多个cell分摊并发压力提高累加器性能,并且用@Contended注解修饰Cell对象,使其能够独占缓存行,解决了缓存行伪共享的问题。而AutomicInteger内部只用一个变量用来表示当前值,在高并发下多个线程争抢该变量性能损耗较大。

  • 相关阅读:
    MongoDB 2023年度纽约 MongoDB 年度大会话题 -- 企业级从传统数据库到NOSQL,你会更好...
    【鸿蒙开发】第十七章 Web组件(一)
    谷歌掀桌子!开源Gemma:可商用,性能超过Llama 2!
    AH4056线性锂电池充电IC:高效、安全的充电解决方案
    java ssm旅游景点景区门票预订及信息发布系统
    qt中数据库和excel互导数据————附带详细步骤和代码
    C语言八进制数(避坑指南)
    APS高级排产帮助企业构建知识化系统,推动数字化发展
    (02)Cartographer源码无死角解析-(20) MapBuilder→MapBuilder()构造函数
    【目标检测算法】利用wandb可视化YOLO-V5模型的训练
  • 原文地址:https://blog.csdn.net/qq_42861526/article/details/127825092