Java的CAS操作

news/2023/12/5 12:11:22

介绍 CAS

技术是为了解决问题而生的,通过 CAS 我们可以以无锁的方式,保证对共享数据进行 “读取 - 修改 - 写回” 操作序列的正确性。

CAS 是乐观锁设计思想的实现。CAS 的思想是:在“读取 - 修改 - 写回”操作序列中,先读取并修改数据,写回数据前先判断读取数据后的这段时间内数据是否发生变化(共享变量的当前值是否是我们的期望值):

  • 如果在此期间数据没有发生变化(共享资源的当前值是我们的期望值),那么就把修改后的值写回
  • 如果在此期间其他的线程修改了数据,数据发生了变化(共享资源的当前值不是我们的期望值),那么就放弃本次写回操作,再基于最新的数据进行修改然后重试,避免发生数据更新丢失

CAS 更加底层的实现依赖于 CPU 提供的特定指令,具体根据体系结构的不同还存在着明显区别。比如,x86 CPU 提供 cmpxchg 指令;而在精简指令集的体系架构中,则通常是靠一对指令(如“load and reserve”和“store conditional”)实现的。在大多数处理器上 CAS 都是非常轻量级的操作,这也是其优势所在。

Java 的 CAS 操作

CAS 依赖于 Unsafe 类提供的一些底层能力,进行底层操作。

/*** Atomically update Java variable to x if it is currently* holding expected.* @return true if successful*/
public final native boolean compareAndSwapInt(Object o, long offset,int expected,int x);

在调用 compareAndSwap() 方法时,我们需要传入需要修改的共享变量、对象偏移量、我们期望的变量当前值、要写回的值。如果变量的当前值和我们的期望值相等,则写回成功,返回 true,否则写回失败,返回 false。

Unsafe 类是 Java 提供的一个操作内存的非安全类,操作对象和对应的变量来完成 CAS 操作。显然 Unsafe 类过于底层,调用 Unsafe 类的方法不是大多数应用场景的最好选择。目前 Java 提供了两种公共 API,可以实现 CAS 操作:

  • 一种是 Atomic 原子类。Atomic 包中的类对 Unsafe 类进行了封装,使我们可以更方便的使用 CAS 操作。Atomic 包提供了常见的原子性数据类型,甚至是引用、数组等相关原子类型和原子更新操作工具。
  • 还有一种是 Variable Handle API,它源自于JEP 193,提供了各种粒度的原子或者有序性的操作等。

CAS 的优劣局限

CAS 的优点:在大多数处理器上 CAS 都是非常轻量级的操作。


CAS 的局限:

  • CAS 操作是针对一个共享变量的,如果需要解决多个变量的原子性问题,建议还是使用互斥锁方案。
  • 存在 ABA 问题:当一个线程在进行 CAS 操作时,另一个线程可能会在此期间修改了同一个共享变量的值,然后又将其改回原来的值。这种情况下,CAS 操作就无法检测到共享变量值的变化,从而导致 ABA 问题。如果我们仅仅在写回数据前判断数值是 A,可能导致不合理的写回操作。针对这种情况,Java 提供了 AtomicStampedReference 工具类,通过为对象引用建立类似版本号(stamp)的方式,来解决 ABA 问题,保证 CAS 的正确性。
  • 如果有大量的线程同时对一个共享变量进行 CAS 操作,竞争过于激烈的情况下,尝试进行 CAS 操作的线程只会白白消耗处理器资源,而不会做任何有价值的工作,这就会带来性能的浪费。

http://www.ppmy.cn/news/75307.html

相关文章

章节2 Matplotlib 绘图基础

目录 课时 2 Matplotlib简介及绘制简单线型图 课时 3 图例和标题 课时 4 自定义图形样式 课时 4 绘制条形图 课时 2 Matplotlib简介及绘制简单线型图 线的画法 plt.plot,同时提供x轴坐标和y轴坐标 课时 3 图例和标题 x 轴数据默认即可,如下所示 x轴代…

plsql为什么连不上远程或本地的Oracle,需要做哪些准备?

文件配置解说 tnsnames.ora文件 文件所在地址:ORACLE_HOME\network\admin ORACLE_HOME:Oracle数据库或者客户端软件所在的地址 但是我的在Oracle数据库的目录下,而不是Oracle客户端软件(instantclient_11_2)下 里…

论文阅读-17-Deep Long-Tailed Learning: A Survey---3.2 Information Augmentation

文章目录 1. Transfer Learning1.1 Head-to-tail knowledge transfer(1) FTL①##### ②##### ③ (2) LEAP(3) OFA(4) RSG(5) M2m(6) GIST(7) MetaModelNet 1.2 Model pre-training(1) DSTL(2) SSP(3) Conceptual 12M 1.3 Knowledge distillation(1) LST(2) LFME(3) RIDE(4) SSD…

STM32F407+LWIP+DP83848以太网驱动移植

最近有个项目上需要用到网络功能,于是开始移植网络相关代码。在移植的过程中感觉好难,网上找各种资料都没有和自己项目符合的,移植废了废了好的大劲。不过现在回头看看,其实移植很简单,主要是当时刚开始接触网络&#…

CMD与DOS脚本编程【第五章】

预计更新 第一章. 简介和基础命令 1.1 介绍cmd/dos脚本语言的概念和基本语法 1.2 讲解常用的基础命令和参数,如echo、dir、cd等 第二章. 变量和运算符 2.1 讲解变量和常量的定义和使用方法 2.2 介绍不同类型的运算符和运算规则 第三章. 控制流程和条件语句 3.1 介…

SVG.js动画——timeline方法与内置控制器

Easing 可以使用runner的ease&#xff08;&#xff09;方法更改动画的缓和程度。 所有可用的ease类型包括&#xff1a; <>: ease in and out : ease out <: ease in-: lineara functionbeziere(x1, y1, x2, y2) // 贝塞尔曲线step(steps, stepPosition) beziere&am…

组件123456789

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

05 Android开机启动之SystemServer

Android开机启动之SystemServer(SS) 一、梳理SystemServer启动流程 从上面整个Android开机启动思维导图(android 5.0的启动组成图)中可以看到: SystemServer是从Zygote中启动的。 开机->bootloader->kernel->init->zygote->SystemServer 二、SystemServe…

Java阶段三Day04

Java阶段三Day04 文章目录 Java阶段三Day04Vue框架Vue框架概述如何引入vue.jsVue框架的HelloWorldVue框架执行原理 基本指令文本相关指令属性绑定和双向绑定事件绑定v-for循环遍历指令显示隐藏相关指令 Vue框架 Vue框架概述 Vue是一种流行的渐进式JavaScript框架&#xff0c;…

彻底理解粘性定位 - position: sticky(IT枫斗者)

彻底理解粘性定位 - position: sticky 介绍 粘性定位可以被认为是相对定位(position: relative)和固定定位(position: fixed)的混合。元素在跨越特定阈值前为相对定位&#xff0c;之后为固定定位。例如: .sticky-header { position: sticky; top: 10px; }在 视口滚动到元素…

springboot使用Mybatis-plus分页插件

1. 引入依赖 在 pom.xml 文件中添加 MyBatis Plus 和分页插件的依赖&#xff1a; <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>{mybatis-plus-version}</version> &…

拿两个字母就能注册商标了吗?

我们来关注一些常见的又让人有点捂脸的现象。比如说&#xff0c;用几个字母或者一个单词注册商标。 黄小明我在办案中就遇到了一个这样的问题。该公司的注册商标被人使用在了一模一样的商品上&#xff0c;然后损失很大&#xff0c;然后该公司就报了警&#xff0c;警察就去把卖假…

Unity UI -- (5)增加基础按钮功能

分析分析一些常见UI 良好的UI设计会清晰地和用户沟通。用户知道他们能和屏幕上哪些东西交互&#xff0c;哪些不能。如果他们进行了交互&#xff0c;他们也要清楚地知道交互是否成功。换句话说&#xff0c;UI要提供给用户很多反馈。 我们可以来看看在Unity里或者在计算机上的任何…

【5.20】五、安全测试——渗透测试

目录 5.3 渗透测试 5.3.1 什么是渗透测试 5.3.2 渗透测试的流程 5.3 渗透测试 5.3.1 什么是渗透测试 渗透测试是利用模拟黑客攻击的方式&#xff0c;评估计算机网络系统安全性能的一种方法。这个过程是站在攻击者角度对系统的任何弱点、技术缺陷或漏洞进行主动分析&#x…

Java中基础数据类型与包装数据类型

文章目录 基础数据类型与包装数据类型有哪些&#xff1f;为什么会有包装数据类型&#xff1f;基础数据类型与包装数据类型两者的区别?包装数据类型的相关方法&#xff1f; 基础数据类型与包装数据类型有哪些&#xff1f; 基本数据类型对应的包装数据类型byteByteshortShortin…

微服务---Redis实用篇-黑马头条项目-优惠卷秒杀功能(使用java阻塞队列对秒杀进行异步优化)

Redis实用篇-黑马头条项目-优惠卷秒杀功能(使用java阻塞队列对秒杀进行异步优化) 1、秒杀优化 1.1 秒杀优化-异步秒杀思路 我们来回顾一下下单流程 当用户发起请求&#xff0c;此时会请求nginx&#xff0c;nginx会访问到tomcat&#xff0c;而tomcat中的程序&#xff0c;会进…

1194: 7208 遍历迷宫

题目描述 迷宫导航是人工智能领域一个常见的问题&#xff0c;迷宫中有走廊和墙壁&#xff0c;机器人可以通过走廊&#xff0c;但不能穿过墙壁。 输入 输入数据文件包含多个测试数据。 每个测试数据的第一行是两个整数&#xff1a;M和N&#xff0c;表示迷宫的大小&#xff0c…

回归分析-简单线性回归推导

回归分析-简单线性回归模型 在大数据分析中&#xff0c;回归分析是一种预测性的建模技术&#xff0c;它研究的是因变量&#xff08;目标&#xff09;和自变量&#xff08;预测器&#xff09;之间的关系。这种技术通常用于预测分析&#xff0c;时间序列模型以及发现变量之间的因…

什么是Java中的Lambda表达式?

在Java 8中引入了Lambda表达式&#xff0c;它是一种匿名函数&#xff0c;可以作为参数传递给方法或存储在变量中。Lambda表达式使得编写简洁、灵活的代码成为可能&#xff0c;并促进了函数式编程在Java中的使用。 Lambda表达式的基本语法如下&#xff1a; javaCopy code (par…

MySQL保证主备一致,如何解决循环复制?

备库只读&#xff0c;是如何和主库同步数据的&#xff1f; 你可能会问&#xff0c;我把备库设置成只读了&#xff0c;还怎么跟主库保持同步更新呢&#xff1f; 这个问题&#xff0c;你不用担心。因为 readonly 设置对超级 (super) 权限用户是无效的&#xff0c;而用于同步更新…
最新文章