首页 > 其他分享 >LongAdder高竞争环境下为什么比AtomicLong块

LongAdder高竞争环境下为什么比AtomicLong块

时间:2023-08-28 19:11:48浏览次数:30  
标签:LongAdder cells collide else 竞争 AtomicLong cs null

 

LongAdder longAdder = new LongAdder();
longAdder.increment(); //依次开始分析

 

LongAdder的基本思路是分散热点,将value值分散到一个Cell数组中。

第一部分:LongAdder.add()

     

第二部分:Striped64.longAccumulate

if ((cs = cells) != null || !casBase(b = base, b + x)) //如果没有创建cells,且base压力过大则进入下一个判断if (cs == null || (m = cs.length - 1) < 0 ||(c = cs[getProbe() & m]) == null ||!(uncontended = c.cas(v = c.value, v + x)))

  

longAccmulate中for循环分三种情况:

case1:cells已经被初始化-------多次重设hash值,多次竞争。谨慎扩容。

case1中的6个分支,我感觉起到的大致作用就是谨慎扩容。

刚开始看源码的时候很奇怪,为什么不是应该确定cells初始化了,且有竞争失败了的情况,要么是cells数组中有的还是null要赋值,要不直接扩容,怎么这么多else if啊?

但仔细看了之后明白自己的想法多么粗糙,如果按我的思路那么基本上竞争失败一次就要扩容,这对空间的消耗太大了,也没考虑CPU是否支持的问题。大佬的代码这些都考虑到了

(1)collide---是否允许扩容

else if (n >= NCPU || cells != cs)
collide = false; // 如果n大于CPU最大线程数量,不可扩容,通过h = advanceProbe(h);修改线程的probe重新尝试
else if (!collide)
collide = true;
else if (cellsBusy == 0 && casCellsBusy())
第一次读的时候感觉collide这个变量没什么作用,但是仔细看了后发现这个变量的作用:(1)如果else if (n >= NCPU || cells != cs)后直接扩容,代码少一次重新设置hash重新竞争的机会,可能造成不必要的扩容
(2)
else if (!wasUncontended) //重新竞争一次,通过h = advanceProbe(h);修改线程的probe重新尝试。还是失败也不会因为wasUncontended再去竞争了
(3)
else if (c.cas(v = c.value,(fn == null) ? v + x : fn.applyAsLong(v, x))) //每次for循环的case1中 大多要经历这个esle if,如果竞争成功则直接退出for,如果失败代码继续向下走。

case2:cells没有加锁且没有初始化,尝试对它加锁并初始化。

             (1)在else if (cellsBusy == 0 && cells == cs && casCellsBusy())之后为什么再进行一次if (cells == cs)判断?

                 网上大部分解释是:防止多线程同时操作进入else if语句中,防止再new一个cell数组。

                 但是:casCellsBusys()调用的是一个CAS函数CELLSBUSY.compareAndSet(this, 0, 1);这个函数本身不起到防止多线程同时操作作用吗?那下面的if (cells == cs)判断到底是什么作用?有大佬给我解释一下吗?

case3:cells正在初始化,则将任务分配到base上

 第三部分:LongAdder.sum()

注意:sum执行的时候,base和cells是可以更新的,所以LongAdder对比AtomicLong的精度要低。

 

 代码感受:(1)涉及多线程的代码if判断大多使用,双重检测和CAS机制,提高代码的健壮性

                   (2)条件判断和要执行的任务大多数尽量合并,让代码更加整洁。

 

标签:LongAdder,cells,collide,else,竞争,AtomicLong,cs,null
From: https://www.cnblogs.com/nowpan/p/17663183.html

相关文章

  • Go race数据竞争检测
    对同一内存的竞争读写,会导致出现数据错乱,是多进程/线程编码中的常见问题。go中提供了race工具协助识别代码中的数据竞争问题。使用起来也非常方便,设计编译的操作时加上-race即可:gotest-racexxxgorun-racexxxgobuild-racexxxgoinstall-racexxx这样编译出来的二进......
  • 14.2 并发与竞争实验
    一、原子操作实验  这节使用原子操作来实现对LED设备的互斥访问,也就是只有一个应用程序能使用LED。 1.实验程序编写  因为是12章已经修改了设备树,所以这里暂时不用修改。  在/linux/atk-mpl/Drivers该目录下创建7_atomic子目录,并且把5_gpioled里面的gpio......
  • 14 Linux 并发与竞争
    一、并发与竞争  并发:多个执行单元同时、并行执行。  竞争:并发的执行单元同时访问共享资源(硬件资源和软件上的全局变量等)易导致竞态。 二、原子操作1.原子操作简介  原子操作:不能再进一步分割的操作,一般用于变量或位操作。  例如在C语言中对无符号整型变量......
  • 期货核心竞争力在于解读供需背后的东西
    我们有理念有方法论。平衡表这个方法是2005年叶总他们摸出来的。原来你看平衡表是没感觉的,后来大家知道,平衡表我们要知道未来半年、未来一年商品的供需平衡情况。还要读懂这个平衡表,很多人是读不懂的,我们以前自己摸索的时候,其它基本不看,我们只是在会议室看这个东西。所有数据都是我......
  • 我反对独立开发者做笔记产品:从商业角度看笔记产品市场竞争
    事情是这样的,刷掘金时看到这篇文章:良言难劝该死鬼,居然有人觉得独立开发做三件套是件好事,这篇文章提到了另一篇文章,是我很喜欢的一个公众号号主和菜头写的一篇《从番茄时钟和记账本开始》;之前在v2ex也看过相关讨论,于是打算好好思考下这件事情,于是在作者的文章下详细写了评价,一写写......
  • 腾讯云 CODING 荣获 TiD 质量竞争力大会 2023 软件研发优秀案例
    点击链接了解详情8月13-16日,由中关村智联软件服务业质量创新联盟主办的第十届TiD2023质量竞争力大会在北京国家会议中心召开。本次大会以“聚焦数字化转型探索智能软件研发”为主题,聚焦智能化测试工程、数据要素、元宇宙、数字化转型、产融合作、未来产业等前沿热点主题......
  • 让 GPT-4 来修复 Golang “数据竞争”问题(续) - 每天5分钟玩转 GPT 编程系列(7)
    目录1.我以为2.阴魂不散的“数据竞争”问题3.老规矩,关门放GPT-43.1复现问题3.2让GPT-4写一个单元测试3.3修复Wait()中的逻辑漏洞4.总结1.我以为我以为GoPool这个项目会昙花一现,从此在GitHub上封尘。关于GoPool项目诞生的故事:《仅三天,我用GPT-4生成了性能......
  • 让 GPT-4 来修复 Golang “数据竞争”问题 - 每天5分钟玩转 GPT 编程系列(6)
    目录1.Golang中的“数据竞争”2.GoPool中的数据竞争问题3.让GPT-4来修复数据竞争问题3.1和GPT-4的第一轮沟通3.2和GPT-4的第二轮沟通3.3提交代码4.总结1.Golang中的“数据竞争”我在上个月发过一篇《跟着GPT-4从0到1学习Golang并发机制(三)》,文中有一节专......
  • 条件竞争漏洞Double Fetch
    前言DoubleFetch(双取)是一种条件竞争的漏洞,相关的论文发表在USENIX,论文链接:https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-wang.pdfDoubleFetchDoubleFetch是内核的一种漏洞类型,发生在内核从用户空间中拷贝数据时,两次访问了相同一块内存。如下图......
  • 传高通停止开发Intel 20A芯片,英特尔输掉了芯片竞争 | 百能云芯
    8月9日,据郭明錤近日发布最新研究报告显示。高通已经停止开发Intel20A芯片。他认为,英特尔欠缺与高通这样的一线IC设计业者合作,将不利于RibbonFET与PowerVia的成长,进一步使得Intel18A研发与量产面临更高不确定性与风险。郭明錤指出,先进制程进入7nm后,一线IC设计业者的高端订单对晶......