首页 > 其他分享 >七、JUC-CAS

七、JUC-CAS

时间:2023-05-27 19:01:36浏览次数:31  
标签:JUC CAS AtomicInteger 内存 atomicInteger public compareAndSet

一、原子类

java.util.concurrent.atomic下所有的类

二、没有用CAS之前

多线程下不使用原子类保证线程安全i++(基本数据类型)

package com.lori.juc2023.juc7;

public class casDemo1 {
    volatile int number = 0;
    //读取
    public int getNumber(){
        return number;
    }
    
    public synchronized  void setNumber(){
        number++;
    }
}

三、使用CAS之后

多线程环境,使用原子类保证线程安全i++(基本数据类型)

package com.lori.juc2023.juc7;

import java.util.concurrent.atomic.AtomicInteger;

public class casDemo1 {
//AtomicInteger 既能保证原子性,又比加锁轻便
   AtomicInteger atomicInteger = new AtomicInteger();
   
   public int getAtomicInteger(){
       return atomicInteger.get();
   }
    
   public void setAtomicInteger(){
       //相当于i++
       atomicInteger.getAndIncrement();
   }
}

四、CAS是什么

1、原理

  • compare and swap的缩写,中文翻译成比较并交换,实现并发算法时常用到的一种技术。
  • 它包含三个操作数:内存位置、预期原值及更新值。
  • 执行CAS操作的时候,将内存位置的值与预期原值比较:
    • 如果相匹配,那么处理器会自动将该位置值更新为新值,
    • 如果不匹配,处理器不做任何操作,多个线程同时执行CAS操作只有一个会成功。

举例说明: CAS有三个操作数,位置内存值V,旧的预期值A,要修改的更新值B。 当且仅当,旧的预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做,或者重来。 当它重来重试的这种行为称为---自旋 123.png

2、代码

package com.lori.juc2023.juc7;

import java.util.concurrent.atomic.AtomicInteger;

public class casDemo1 {


    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(5);
        //看原始值是不是5,如果是5的话,将5修改为2023
        boolean compareAndSet = atomicInteger.compareAndSet(5, 2023);
        System.out.println(compareAndSet+"\t"+atomicInteger.get());
    }


}
  • 第一次执行结果: 124.png
  • 如果加多一次修改
package com.lori.juc2023.juc7;

import lombok.val;

import java.util.concurrent.atomic.AtomicInteger;

public class casDemo1 {


    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(5);
        //看原始值是不是5,如果是5的话,将5修改为2023
        boolean compareAndSet = atomicInteger.compareAndSet(5, 2023);
        System.out.println(compareAndSet+"\t"+atomicInteger.get());
        boolean andSet = atomicInteger.compareAndSet(5, 2023);
        System.out.println(compareAndSet+"\t"+atomicInteger.get());

    }
}

125.png

3、硬件级别的保证

  • CAS是JDK提供的非阻塞原子性操作,它通过硬件保证了此较-更新的原子性。它是非阻塞的且自身具有原子性,也就是说这玩意效率更高且通过硬件保证,说明这玩意更可靠。
  • CAS是一条CPU的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe提供的 CAS方法(如compareAndSwapxxx)底层实现即为CPU指令cmpxchg。
  • 执行cmpxchg指令的时候,会判断当前系统是否为多核系统,如果是就给总线加锁,只有一个线程会对总线加锁成功,加锁成功之后会执行CAS操作,也就是说CAS的原子性实际上是CPU实现独占的,比起用synchronized重量级锁,这里的排他时间要短很多,所以在多线程情况下性能会比较好。

126.png

  • var1:要操作的对象
  • var2:标识要操作对象中属性地址的偏移量
  • var4:表示要修改数据的期望值,也就是上一个版本拿到的值
  • var5/var6:表示要修改为的新值

4、谈谈对Unsafe类的理解

127.png

  • UnSafe类是CAS的核心类,由于Java犯法无法直接访问底层系统,需要通过本地方法native来访问,Unsafe相当于一个后门,基于该类可以直接操作特定的内存数据。Unsafe类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,因为Java中CAS操作的执行依赖于Unsafe类的方法。
  • 注意:UnSafe类中所有的方法都是native修饰的,也就是说UnSafe类中的方法都是直接调用操作系统底层资源执行相应的任务。
  • 变量valueOffset,表示该变量值在内存中的偏移地址,因为Unsafe就是根据内存偏移地址获取数据的 128.png
  • 变量value用volatile修饰,保证了多线程之间的内存可见性

1、i++线程不安全,通过atomicInteger.getAndIncrement()保证线程安全

  • CAS的全称是Compare-And-Swap,它是一条CPU并发原语
  • 它的功能是判断内存某个位置是否为预期值,如果是则修改为新值,这个过程是原子的
  • AtomicInteger类主要利用CAS+volatile和native方法来保证原子性,从而避免synchronized的高开销,执行效率大为提升。

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

标签:JUC,CAS,AtomicInteger,内存,atomicInteger,public,compareAndSet
From: https://blog.51cto.com/u_15410237/6362915

相关文章

  • Cassandra中的MerkleTree反熵机制
    构建MerkleTreeCassandra是一个分布式数据库系统,它使用Merkle树来实现数据一致性和数据完整性的验证。在Cassandra中,每个节点都维护着自己的数据副本。为了确保数据的一致性和完整性,Cassandra使用Merkle树进行验证。Merkle树是一种树状结构,由哈希值构成,用于对数据块进......
  • 使用static_cast进行父类指针转子类指针可能出现的问题
    使用static_cast进行父类指针向子类指针的转换,可能会出现以下问题:如果转换的父类指针并不是指向真正的子类对象,而是指向另一个父类对象,那么转换后的子类指针将指向无效的内存地址,可能导致程序崩溃。如果子类对象中有虚函数或虚继承,static_cast可能会失效,因为它只进行编......
  • Jmeter函数助手31-changeCase
    changeCase函数用于字符转换大小写。字符串修改:填入需要转换的字符更改案例模式UPPER(默认),LOWER,CAPITALIZE:不填默认UPPER,UPPER全部转换为大写,LOWER全部转换为小写,CAPITALIZE将首字母转换大写存储结果的变量名(可选) 1、UPPER全部转换为大写。${__changeCase(TodayisSaturd......
  • Hugging News #0526: Hugging Cast 发布第一期、邀请来认领自己的论文啦!
    每一周,我们的同事都会向社区的成员们发布一些关于HuggingFace相关的更新,包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等,我们将其称之为「HuggingNews」,本期HuggingNews有哪些有趣的消息,快来看看吧!重磅更新HuggingCast播客#1发布Hugg......
  • 五、JUC-Java内存模型JMM
    一、一些疑问什么是Java内存模型JMMJMM与volatile他们两个之间的关系JMM有哪些特性为什么要有JMM,他们为什么出现,功能和作用是什么happens-before先行发生原则是什么二、计算机硬件存储体系计算机存储结构,从本地磁盘到主存到CPU缓存,也就是从硬盘到内存到CPU一般对应的程序......
  • [Chirpstack] device和Multicast groups不能绑定
    背景:Chirpstack可以添加device和Multicastgroups,但是不能绑定解决办法:通过api绑定device和Multicastgroups 绑定成功之后可以继续通过api向组播下发downlinkdata  节点可以收到组播下行 ......
  • 四、JUC-LockSupport与线程中断
    一、线程中断机制1、概述一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以,Thread.stop、Thread.suspend、Thread.resume都已经被废弃了在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于......
  • 面试中被问到CAS机制该怎么回答
    一个小例子说说什么是线程安全并发是Java编程的基础,在我们日常的工作中,很多时候都会跟并发打交道,当然,这也是面试考察的重点。在并发编程中,被提起最多的概念是线程安全,下面我们先来看一段代码,看看运行后会发生什么:publicclassTest{privatestaticintinc=0;public......
  • PyTorch-Forecasting一个新的时间序列预测库
    时间序列预测在金融、天气预报、销售预测和需求预测等各个领域发挥着至关重要的作用。PyTorch-forecasting是一个建立在PyTorch之上的开源Python包,专门用于简化和增强时间序列的工作。在本文中我们介绍PyTorch-Forecasting的特性和功能,并进行示例代码演示。完整文章:https://av......
  • 基于Lucas-Kanade算法的双目图像光流提取matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:      2.算法涉及理论知识概要        1950年,Gibson首先提出了光流的概念,所谓光流就是指图像表现运动的速度。物体在运动的时候之所以能被人眼发现,就是因为当物体运动时,会在人的视网膜上形成一系列的连续变化的......