AtomicInteger原理和CAS与Synchronized(juc编程)

AtomicInteger原理

4.6.1 原理介绍

AtomicInteger的本质:自旋锁 + CAS算法

CAS的全成是: Compare And Swap(比较再交换); 是现代CPU广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。CAS可以将read-modify-write转换为原子操作,这个原子操作

直接由处理器保证。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当旧预期值A和内存值V相同时,将内存值V修改为B并返回true,否则什么都不做,并返回false。

举例说明:

  1. 在内存值V当中,存储着值为10的变量。
    在这里插入图片描述

  2. 此时线程1想要把变量的值增加1。对线程1来说,旧的预期值 A = 10 ,要修改的新值 B = 11。

在这里插入图片描述

  1. 在线程1要提交更新之前,另一个线程2抢先一步,把内存值V中的变量值率先更新成了11。
    在这里插入图片描述

  2. 线程1开始提交更新,首先进行A和内存值V的实际值比较(Compare),发现A不等于V的值,提交失败。
    在这里插入图片描述

  3. 线程1重新获取内存值V作为当前A的值,并重新计算想要修改的新值。此时对线程1来说,A = 11,B = 12。这个重新尝试的过程被称为自旋
    在这里插入图片描述

  4. 这一次比较幸运,没有其他线程改变V的值。线程1进行Compare,发现A和V的值是相等的。
    在这里插入图片描述

  5. 线程1进行SWAP,把内存V的值替换为B,也就是12。

在这里插入图片描述

举例说明:这好比春节的时候抢火车票,下手快的会抢先买到票,而下手慢的可以再次尝试,直到买到票。

4.6.2 源码分析

那么接下来我们就来查看一下AtomicInteger类中incrementAndGet方法的源码。

public class AtomicInteger extends Number implements java.io.Serializable {// cas算法的实现类private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();// 表示变量值在内存中的偏移量地址,unsafe类就是根据内存偏移量地址获取数据值。private static final long VALUE = U.objectFieldOffset(AtomicInteger.class, "value");private volatile int value;// 以原子方式将当前值加1,这里返回的是自增后的值public final int incrementAndGet() {/* this表示当前AtomicInteger对象 ,1表示要增加的值 */return U.getAndAddInt(this, VALUE, 1) + 1;		// 调用Unsafe类中的getAndAddInt方法}}

UnSafe类

public final class Unsafe {// Unsafe类中的getAndAddInt方法public final int getAndAddInt(Object o, long offset, int delta) {int v;// do...while就是自旋操作,当CAS成功以后,循环结束do {// 获取AtomicInteger类中所封装的int类型的值,就相当于旧的预期值Av = getIntVolatile(o, offset); // 调用本类的weakCompareAndSetInt方法实现比较在交换; o: AtomicInteger对象, v: 相当于旧的预期值A, v + delta:新值B} while (!weakCompareAndSetInt(o, offset, v, v + delta));return v;}// Unsafe类中的weakCompareAndSetInt方法public final boolean weakCompareAndSetInt(Object o, long offset, int expected, int x) {return compareAndSetInt(o, offset, expected, x);}// 本地方法,调用CPU指令实现CASpublic final native boolean compareAndSetInt(Object o, long offset, int expected, int x);}

4.7 CAS与Synchronized

CAS和Synchronized都可以保证多线程环境下共享数据的安全性。那么他们两者有什么区别?

Synchronized是从悲观的角度出发:

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线

程阻塞,用完后再把资源转让给其它线程)。因此Synchronized我们也将其称之为悲观锁。jdk中的ReentrantLock也是一种悲观锁。

CAS是从乐观的角度出发:

总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。CAS这种机制我们也可以将其称之为乐观锁。

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

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

相关文章

关于椭圆的方程(有Python画的动图)

关于椭圆的方程(有Python画的动图) flyfish 几何定义 椭圆是平面上所有到两个固定点(焦点)的距离之和为常数的点的集合。这两个固定点叫做焦点。 解析几何描述 设椭圆的两个焦点为 F 1 F_1 F1​ 和 F 2 F_2 F2​&#xff…

【高等数学】傅里叶级数

最近刷了会抖音,看到一个非常有趣的现象:傅里叶级数,今天挑了几个视频来供大家学习。 1.傅里叶级数概念 【小崔说数】傅里叶级数专题https://www.bilibili.com/video/BV1Uq4y1q7xk?t117.4 2.傅里叶级数动画 【谜之舒适】12分钟的傅立叶级…

【docker】Dockerfile制作基础镜像 python 底层镜像制作 | 打包所有的requirement依赖

一、Dockerfile思想 我们正常的对一个项目进行打包 docker image 通常是在CI工具编译时进行对依赖的安装,比如golang的go get、python的pip install、node的npm install 等等 好处:我们更新了依赖可以动态的再编译时进行一个对依赖的更新 坏处&#xf…

转速传感器频率信号整形方波输出隔离变送器 地线干扰抑制 200mV~10V/0-12V/0-24V转0-5v/0-12v/0-24v/集电极输出

特点 转速传感器信号直接输入,方波信号输出正弦波、锯齿波信号输入,方波信号输出200mV峰值微弱信号的放大与整形不改变原波形频率,响应速度快电源、信号:输入/输出 3000VDC三隔离辅助电源:5V、12V、15V或24V直流单电源…

在4面体空间内2点结构占比

有一个4面体状空间,由3层甲烷状分子堆积而成,单个甲烷4面体边长10. 内有30个点,在30个点中取2点,有30*29/2435种取法。这里要求两个点的距离必须为6.123 在435个结构中只有40个符合要求 序数 结构 序数 结构 3 1 282 3 7…

如何进行海外网络加速?告别卡顿与访问慢的方法

你是否经常在打开海外网站浏览网页时遇到响应缓慢的问题?或者在进行国际网络会议时,由于网络延迟影响与客户的交流?亦或是由于网络问题,导致OA、ERP、云储存等应用频繁因为数据包丢失而中断下载?如果你经常遇到这些问题…

centos7 离线安装zip和unzip

解压的时候发现不能解压,报-bash: unzip: command not found 1、访问https://www.rpmfind.net/linux/rpm2html/search.php?queryzip&submitSearch…&systemcentos&arch#/ 2、输入zip和centos搜索,选择el7下载 3、输入unzip和centos搜索&am…

显卡nvidia的CUDA和cuDNN的安装

显卡版本,和nvidia下载的 CUDA版本和CUDNN的关系 1. 显卡版本 nvidia-smi 硬件环境:显卡版本 4090 NVIDIA-SMI-555.85 我的驱动是510.85.02,驱动附带cuda12.5 2. nvidia下载的cuda版本 nvcc -V 我下载的是cuda12.5 cuda在安装版本过程…

互联网技术基础-计算机人必看

目录 1.Internet的工作原理 1、Internet是一个分组交换系统 2、路由器是Internet实现互连的“标准件” 3、TCP/IP是Internet的核心协议 4、客户机/服务器的工作模式 2. IP地址 2.1 IP地址分类 2.2特殊IP地址 2.3路由器和IP编制原则 2.4子网的划分 2.5 IPV6 3.域名系…

【因果推断python】46_估计量2

目录 连续型干预变量案例 非线性处理效果 关键思想 连续型干预变量案例 目标转换方法的另一个明显缺点是它仅适用于离散或二元处理。这是你在因果推理文献中经常看到的东西。大多数研究都是针对二元干预案例进行的,但您找不到很多关于连续干预的研究。这让我很困…

Bytebase 对接本地部署的 llama3 开启ChatSQL功能

Bytebase 是为开发人员、测试、DBA和运维工程师构建的数据库 DevOps 领域的,类 GitLab/GitHub 平台。 这篇文章主要关注 Bytebase SQL 编辑器中的 AI 增强功能。使用此功能您可以使用自然语言在 Bytebase SQL 编辑器中查询数据库。同时还能给出针对查询的索引建议&…

RK3568技术笔记十四 Ubuntu创建共享文件夹

单击“虚拟机”,单击“设置”,如图所示: 单击“选项”,选择“总是启用(E)”,单击“添加”,如图所示: 单击“下一步”,如图所示: 单击“浏览”添加…

Ranger配置图片及json文件预览

文章目录 前言下载apt下载pip下载 配置使用json文件预览方法一 修改scope用cat预览方法二 安装jq预览配置ranger 图片文件预览方法一 使用img2txt预览方法二 使用fim预览配置ranger 总结 前言 本文主要讲解Ranger12如何配置json及图片的预览设置,如下是ranger的介绍…

Spring AI 整合openAI的chatGpt

Spring AI支持ChatGPT,这是OpenAI的AI语言模型。ChatGPT在激发人们对人工智能驱动文本生成的兴趣方面发挥了重要作用。 SpringAi与Spring Boot 的整合详见上一篇文章: Spring AI 介绍以及与 Spring Boot 项目整合 下面分四个部分来分别说明和演示&#…

简单分享github

一、官网 GitHub: Let’s build from here GitHub 二、注册 通过简单的注册步骤,你就可以拥有一个属于自己的GitHub账号。再简单注册完成之后会需要验证你所输入的邮箱才能正常使用你的GitHub。 三、设置自己的库 在注册完成之后,完成一些简单的设置之…

简单且高效的水域物探轨迹坐标转换程序

简单且高效的水域物探轨迹坐标转换程序 前言 水上测线的高精度定位是水域物探的难题,水域磁法、水域地震实施时常采用船舶拖拽传感器进行走航式观测,GPS仪器放在船舶上测量,造成船舶位置与传感器位置存在偏差,后期资料整理需要校…

互联网应用主流框架整合之Spring Boot基本概念

Spring Boot是用来简化Spring应用程序的搭建、开发、测试和部署过程的,该框架使用了特定的方式进行配置,从而使开发人员不再需要定义样板化的配置,SpringBoot致力于快速应用开发(Rapid Application Development)领域的发展,它通过…

RTSP/Onvif安防监控平台EasyNVR抓包命令tcpdump使用不了的解决方法

安防视频监控汇聚EasyNVR智能安防视频监控平台,是基于RTSP/Onvif协议的安防视频平台,可支持将接入的视频流进行全平台、全终端分发,分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等格式。平台可提供的视频能力包括:…

vscode插件开发之 - TestController

TesController概要介绍 TestController 组件是用于实现自定义测试框架和集成测试结果的。它允许开发者定义自己的测试运行器,以支持在VSCode中运行和展示测试。以下是一些使用 TestController 组件的主要场景: 自定义测试框架:如果你正在开发…

C++语法19 循环嵌套结构(for/while循环)

语法阶段已经更新到第18章了,前面的知识你都学会了吗?如果还没有学习前面的知识,请点击👉语法专栏进行学习哦! 目录 循环嵌套 训练:数字矩形 解析 参考代码 训练:星号三角形 解析 参考代码 …