Java-多线程并发之原子操作类原理剖析
AtomicLong:主要进行一些自增自减和交换操作。原子性的前提下用的是非阻塞CAS的方法,比Synchronized效率高。但是高并发下仍会同时竞争一个原子变量。
但是java提供了一个更好用的LongAdder
LongAdder:
维护一个几只基值变量base和一个Cell数组。Cell数组可以看作是AtomicLong的改进,用来解决共享问题。
LongAdder相当于将Atomic中的原子变量分裂成幂次方个,线程的压力就少了很多。而且LongAdder是惰性加载,延迟初始化,初始化的时候Cell数组是null,累加操作数据都放在基值变量base上。初始化时候,cell的变量为2,Cell数组的变量实体是Cell.
对于多个原子操作进行字节填充是浪费的,因为原子操作都是无规律的散放在内存中。但是这里的原子性数组是内存地址连续的,刚才说的散放的是不同的原子性操作。
所以原子数组内多个元素经常可以共享到一个缓存行,一般用注解的方式@sun.misc.Contended.性能会有所提升。
通过源代码可以看出,通过cellBusy对数组的初始化和扩容操作进行自旋锁操作,在0/1切换。在初始化或开始扩容阶段要设置为1,初始化完成或结束后设置为0,这样可以避免其他线程的打扰。
扩容的条件是满足
1.cell元素个数小于CPU数目
2.多线程访问cell的同一个元素导致CAS失败
关于CAS失败,LongAdder的做法是重新计算一个probe值。Probe值的作用有点儿类似于hashcode.通过随机的值来确定当前的线程应该存放到哪个cell中去。
LongAdder是LongAccumulator的一个特例。
LongAccumulator的功能更加强大,可以让用户去自定义累加规则。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!