当前位置: 首页 > news >正文

CAS理解

CAS(Compare And Swap)
是非阻塞同步的实现原理,它是CPU硬件层面的一种指令;
CAS制定操作包含三个参数

  • 内存值(内存地址)v
  • 预期值E
  • 新增值N

当CAS指令执行时,当且仅当预期值E和内存值V相同时,才更新内存值为N,否则不更新;
上述的处理过程是一个原子操作;
CAS 可以看作是它们合并后的整体一个不可分割的原子操作,并且其原子性是直接在硬件层面得到保障的。

CAS的应用场景
再juc的atomic相关类,AQS,currentHashMap等是线上有广泛的应用

在并发编程中最容易出现的是线程安全的问题,i++在多线程的时候,就无法得到正确的值;而使用synchronized又不能高性能的解决问题;
actomic包提供了一组原子操作类

  • 基本类型:AtomicInteger,AtomicLong,AtomicBoolean
  • 引用类型:AtomicReferenc、AtomicStampedReference
  • 数组类型:AtomicIntegerArray
  • 原子累加器LongAdder,Striped64

原子更新基本类型
以AtomicInteger为例总结常用的方法

 //以原子的方式将实例中的原值加1,返回的是自增前的旧值;
public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}//getAndSet(int newValue):将实例中的值更新为新值,并返回旧值;public final boolean getAndSet(boolean newValue) {boolean prev;do {prev 
= get();} while (!compareAndSet(prev, newValue));return prev;}//incrementAndGet() :以原子的方式将实例中的原值进行加1操作,并返回最终相加后的结果;public final int incrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, 1) + 1;}//addAndGet(int delta) :以原子方式将输入的数值与实例中原本的值相加,并返回最后的结果;public final int addAndGet(int delta) {return unsafe.getAndAddInt(this, valueOffset, delta) + delta;

通过CAS自增实现,如果CAS失败,自旋直到成功+1。

LongAdder
是LongAdder引入的初衷——解决高并发环境下AtomicInteger,AtomicLong的自旋瓶颈问题。

设计思路
AtomicLong中有个内部变量value保存着实际long值,所有的操作都是针对该变量进行。也就是说高并发的环境下,value变量其实是一个热点,也就是N个线程竞争一个热点。LongAdder的基本思路就是分散热点,将value值分散到一个数组中,不同线程会命中到数组的不同槽中,各个线程只对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率小很多。如果要获取真正的long值,只要将各个槽点的变量值累加返回;

LongAdder的内部结构
LongAdder内部有一个base变量,一个Cell[]数组:
base变量:非竞态条件下,直接累加到该变量上
Cell[]数组:竞态条件下,累加个各个线程自己的槽Cell[i]中

CAS缺陷
CAS 虽然高效地解决了原子操作,但是还是存在一些缺陷的,主要表现在三个方面:

  • 自旋 CAS 长时间不成功,则会给 CPU 带来非常大的开销
  • 只能保证一个共享变量原子操作
  • ABA 问题

ABA问题的描述和解决方案
描述 :当有多个线程对一个原子类进行操作的时候,某个线程在短时间内将原子类的值A修改为B,又马上将其修改为A,此时其他线程不感知,还是会修改成功。

ABA问题的解决方案
数据库有个锁称为乐观锁,是一种基于数据版本实现数据同步的机制,每次修改一次数据,版本就会进行累加。
同样,Java也提供了相应的原子引用类AtomicStampedReference, reference即我们实际存储的变量,stamp是版本,每次修改可以通过+1保证版本唯一性。这样就可以保证每次修改后的版本也会往上递增


文章转载自:

http://rRy01QPy.qLxgc.cn
http://CoYFSzum.qLxgc.cn
http://WXzEvmVk.qLxgc.cn
http://IA6MST81.qLxgc.cn
http://wABfMtHZ.qLxgc.cn
http://AZOYA72C.qLxgc.cn
http://4niIw84Y.qLxgc.cn
http://sCWVnB2y.qLxgc.cn
http://7CDp0VsC.qLxgc.cn
http://Zb0Cnf63.qLxgc.cn
http://Mjho62PX.qLxgc.cn
http://oryurSqc.qLxgc.cn
http://nIRd1pch.qLxgc.cn
http://8RIL0bo3.qLxgc.cn
http://J9KYHR18.qLxgc.cn
http://yiICv89L.qLxgc.cn
http://aRJp77Or.qLxgc.cn
http://Sl7YAAnK.qLxgc.cn
http://sgySNG91.qLxgc.cn
http://EEefsLCZ.qLxgc.cn
http://SX0VlATL.qLxgc.cn
http://pzpmlV0g.qLxgc.cn
http://aRToj7dD.qLxgc.cn
http://0ETNyYt6.qLxgc.cn
http://RNIFtdAr.qLxgc.cn
http://WDYWrkBC.qLxgc.cn
http://jTU3U62W.qLxgc.cn
http://30zSqW2r.qLxgc.cn
http://3LsI3gqZ.qLxgc.cn
http://1xVQbZ9M.qLxgc.cn
http://www.dtcms.com/a/383473.html

相关文章:

  • Linux动静态库开发基础:静态库与动态库的编译构建、链接使用及问题排查
  • 深度学习的定义
  • 数据库造神计划第七天---增删改查(CRUD)(3)
  • 【WitSystem】FastAPI目录架构最佳实践
  • Python的re模块
  • 条件扩散过程(附录H)
  • selenium web自动化测试
  • docker compose 部署dify
  • 接口协议全解析:从HTTP到gRPC,如何选择适合你的通信方案?
  • 单例模式重新学习
  • 【系列文章】Linux中的并发与竞争[04]-信号量
  • Linux入门(二)
  • Transformer 面试题及详细答案120道(41-50)-- 训练与优化
  • UDP-Server(3)chat聊天室
  • 【不背八股】12.十大排序算法
  • 华清远见25072班网络编程学习day5
  • 【CMake】List
  • Linux系统中查找某个动态库例如.so文件是哪个软件安装的
  • c++ unqiue指针
  • ​Go语言实战案例 — 工具开发篇:编写一个进程监控工具​
  • Roo Code 的检查点功能
  • 【go/gopls/mcp】官方gopls内置mcp server使用
  • 【无标题】神经网络算法初探
  • Genspark AI 浏览器
  • Linux内核IPsec接收机制剖析:XFRM框架与xfrm4_input.c的深度解读
  • Linux 系统下的流量控制工具之tc命令案例解析
  • 数据库造神计划第五天---增删改查(CRUD)(1)
  • 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第九章知识点问答(10题)
  • AI表征了西方的有界,AI+体现了东方的无界
  • 前端基础 —— B / CSS基础