大家好,我是Axuan。
每当我们谈论并发时,我们心中的第一印象就是Conturenthashmap类。实际上,这堂课的许多并发设计思想值得我们参考。当我想帮助浏览器时,我发现许多文章都是Ctrl+Ctrl+V。根本没有提及许多细节。我只能冷静下来。我研究了本文。对于详细的分析,该版本为JDK1.8.0_241。至于7和8之间的差异,互联网上已经有很多文章。本文将不会继续。
放置源代码相对较长,让我们首先看一半
putval
第一个如果判断集为空,请初始化空气
在里面
这是sizectl的变量
他被修改,具有线程的可见性,在初始化和扩展时为负,而其他时间为正数。
当我第一次进入周期时,它是积极的,所以它会归功于②。在这里,您将使用CAS执行免费锁定分配。CAS中的下一个线程失败的螺纹未能让CPU时间胶片。
CAS的成功线将初始化数组。当我们立即同时使用contrenthashmap时,如果通过初始容量,它将对传递参数执行一系列的位操作,最后获得2 -2功率的2 -2功率背景,如果未传递初始容量,然后站点等于默认值0,因此,如果传递初始容量,则N等于计算值,并且没有传输等于默认值
因此,confurrenthashmap的默认初始化容量为16。与哈希姆普一样,在初始数组之后,Sizectl的大小将设置为(容量x0.75),作为容量的下一个阈值。发现后的循环
返回Putval方法,目前开始判断,并通过该方法找到目标索引位置的值,该方法等同于容量的剩余能力,并计算目标位置i的索引位置。
这是不安全方法的值。GetObject Volative具有Valotile的语义,可以在I索引上获得最新值。如果值为null,请创建一个新的节点对象,然后通过CAS分配值以分配值
如果CAS分配成功,则循环跳出,分配失败,输入下一个周期,然后进入③,确定目标节点的哈希值是否相等,即-1,-1,
如果等同于帮助扩张和扩展能力,那么让我们谈谈最后的判断
如果目标索引位置的值既不为null也不扩大容量,则直接开始判断节点的密钥是否相等。
一些读者可能会在这里思考,以前的作业中使用了什么,那么您还可以在这里使用CAS吗?
Axuan想到了。实际上,这里没有办法在这里使用它
原因是3分
我们继续低头看,然后立即做出了判断。这个判断很容易被忽略,但是
例如,在先前的IF执行之后,在锁定之前,此f节点刚刚由扩展线程操作,然后目前tabat(tab,i)!
下一步是判断它是否是算法工具的应用。本文没有解释本文
然后,我们查看链接列表。首先,我们将确定头节点是否满足要求。满足要求时,值将给出值。该变量意味着仅在不存在时才分配。如果是正确的,则将值分配给null.为null,而不是分配值,仅返回原始值。这是错误的,因此它将涵盖原始值。
如果节点不相遇和向下浏览,则整个链接列表不排队,则将通过执行锁定结构的执行来判断插入链接列表末尾的新节点的新节点。红树和黑色树的阈值是链列表的阈值是它是相同的值还是两个结构不想经常互相更改。
最后,如果有合格的密钥,则返回原始值。如果没有存在,您将跳出周期。执行方法的最后一个逻辑方法只有在整个集合中没有合格的密钥时才能执行,否则原件将返回到原始键。值,预先返回,让我们看一下AddCount方法。
addCount
它主要分为2个大块,第一个IF是计算,第二个是判断。在查看它之前,读者可能希望考虑这个问题。那高并发呢?
道格在这里给出了答案,我该如何实现思想的能力并有效地计算能力?
道格(Doug)有一个长类型的变量,类型的数组,而Countrecell实际上只有一个长变量。
读者是否注意到此类使用注释。这个注释很奇怪吗?他的角色是防止它。这是一篇文章。有兴趣的读者可以研究它。
因此,计算容量的总体想法是首先尝试+1。如果失败,则随机在数组中随机获得较低的出价,然后对他尝试+1,以便将容量的并发操作分开,这极大地出现,大力证明了并发性能,理想情况下,最有支撑的线程可在能力下运行能力。同时。
理解这一点之后,当我们查看代码时,我们会更加放松
我第一次输入此方法时,默认值是这样做的,因此我将尝试通过CAS执行+1操作。如果您成功地跳出IF进行下一个判断,则将存在故障。首先,将执行判决。总共4个条件。前两个条件是确定反电池阵列是否为空。第三个条件是根据线程值计算阵列的竞标,然后确定竞标是否为null。
探测
该方法的含义是获得线程之一。在这里,我们看到了我刚才提到的注释。实际上,此注释实际上是在其中使用的
最后的条件是为刚刚通过CAS获得的阵列的县分配值。
在这里,我不知道读者是否注意到了一个细节,这是不可能的。作者在这里巧妙地使用了它
如果Countrcell Array为Null,请首先操作。如果成功很高兴,则失败表明有同时进行的竞争,并且需要初始化阵列。执行以下操作。如果Counter Counter Array不是空的,则意味着已经存在现有的竞争。目前,它正在针对CAS进行操作,最好直接操作Countrecell数组,因此它将直接进入IF内部而不会执行后来的CAS。
当输入内部IF判断时,由于目前的反电池阵列不是null,如果第三个条件为null,则该方法输入了初始化此较低出价的方法。它不会尝试尝试较低的出价来进行CAS.ASSIGNMENT操作,成功跳出IF,失败也进入了方向。
稍后将提及全addcount方法,在这里不会提及,但是这里存在一个问题,我从来没有想了解的问题,也就是说,第一个if中有2个。您为什么要在这里返回?如果有些读者知道,请在评论区域回答,非常感谢!
继续查看第二个如果判断②,则周期是上面计算的设置容量,即扩展阈值,因此这是确定是否需要扩展的集合集合
让我们先看一下这个方法
上半场是将n转换为从左到右计算,例如n = 16
16
从左到右有27 0,因此计算值为27,因此该值的值在1-32之间并转换为二进制
,下半场意味着1
然后,等效,然后resizestamp的最大值和最小值为
您可以找到最大值或最小值。在此值下,将立即使用
然后,如果判断将有两个。首次输入此周期时,它等于膨胀阈值。它大于0。如果将进入第二个。条件是通过cas.在一个周期中分配一个值,给定的值是多少?我们只是计算容量的值,然后,然后添加2,这是什么意思?
实际上,在容量扩展之后保存的Sizectl的值,这表明这意味着当我们阅读时,我们可能会认为它可以用于节省容量并构建变量以节省线程数。
实际上,这也是JDK的主要功能。如果您阅读了太多有关源代码的信息,您会发现许多地方都这样玩。保存一个值是16-1位,较低的16位可以节省另一个值。
因此,该线程再次循环,因为它目前已经是负面的,因此它将输入第一个IF。这是展示操作的另一波浪潮。我们一一看到。加法和减法的添加和减法刚刚开始
这里还有另一个。您是否发现这里使用的是,当您以前分配值时,如何有箭头?>>>意味着,如果右前为负,则右移动0后的高位置要组成0 0.它将成为正数。相应地,在正确移动之前是负数,负数仍在正确的移动之后,因此第一个条件是确定容量是否已更改
第二和第三条件实际上是。维修,请参阅Oracle的官方网站。正确的条件应该是
首先是确定扩展容量的线程数量是否为0。读者可能有疑问。起初不是吗?为什么是这样?因为第一个扩展线程在开始时已经计算出自身,然后+1自己,所以第二个是+2,第二个是确定扩展线程是否达到最大线程数的最大数量
最后两个条件是确定扩展后的阵列是否为无效,以及容量的较低竞标位置是0,即扩展是否结束
整个IF的五个条件是确定扩展是否结束。实际上,它仍然是隐藏的。稍后,当提到转移方法时,将讨论
如果目前没有扩展,则分配+1操作由CAS分配,成功方法将有助于扩展。在周期结束时,将执行设定容量的计算操作。
确定是否需要再次进行扩展,一些读者可能会怀疑,它是否会触发扩展的扩展,您会在转移方法完成后知道。由于完成扩展的线程时,将执行扩展的线程。如果判断,转移必须等于0,则不会再次输入转移方法。只有最后一个线程可能会再次触发扩展操作
AddCount基本上在这里完成。
此方法有点长,我们分为4个部分来解释,
我将判断我第一次进入时是否是0。如前所述,此值是线程。如果是0,请初始化
从源代码可以看出,初始化后的值是,如果0更改为1,为什么不为0,这将在后面提及
接下来,我将输入一个。循环主要分为3个大块,短暂
首先判断反电池阵列,如果要为空,请输入第二个,请尝试
该代码相对简单,初始化一个容量为2的数组,然后创建一个新对象,以将值分配给目标索引位置,以及出口循环的初始化
如果反电池的数量数组为空,则初始化将再次失败,此时,您将再次尝试制作CAS。如果成功,
接下来,我们专注于第一个,其中有几个
第一个if
它分为6个判断,①确定目标索引位置是否为null,并将无效尝试设置为1
该变量也经过修改,并用于控制数组的操作。看到这一点,读者可能有疑问,哈哈,有很多问题
为什么您在这里连续两次判断?
在这里,您只能说道格的“问题”再次提出。请注意,我在这里添加。
怎么说
因为在这里将执行操作,所以CAS也是一个。既然锁定了,那么我们将存在。我们都知道,锁定间隔越小,最低限度,因此老人道格当然知道,它也知道它也知道。新对象?
当时,它实际上将存在,因此采用JVM
您是否认为新的外观非常简单,并且其中有很多东西,因此老人已经操作了新对象的操作。目的是这样做。无论如何,即使背部中的CAS失败,它也会再次发生。欣赏,钦佩
②该判断是另一个细节。此变量仅在此判断中从头到尾使用。您是否曾经想过这个变量是什么?
这个变量名称实际上是翻译,这是什么意思,什么是竞争?
让我们看一下这里将实现哪些条件。从上面的话,可以看到这里必须满足
该方法只有一个入口,这是之前的说法。我们正在回顾输入此方法的条件
根据上面获得的两个条件,只有一种方法可以在满足这两个条件时进入方式。
回到方法,如果这种情况是这种情况,则将再次执行,并且在两个CAS操作之间没有时间 - 耗费的操作,然后这次,CAS将通过它实现,并且也有一些。
因此,您知道为什么表演如此之高,对吗?
③通过CAS的任务,成功退出,无话可说
③④,我又来了(手动哭泣),刚才我们分析了,当执行它时,它已经是,再加上它已经是,现在应该考虑什么?
当然,对,这里有一个变量,翻译是含义,上半部分是确定是否已经是已经扩展的,然后将其设置为默认值。我只是扩大了能力。如果没有扩大能力,则判断力更大。如果较少,则意味着,因为从理论上讲,有最多支持数组同时支持阵列,因此下一个如果要执行判断。
④为什么这个判断使用它?它看起来与②②相似,并且角色相似,也就是说,再次查看它是否可以成功。如果没有成功,那就没有办法。(无助)
最后,来到⑤,也就是说,在这里没有什么可说的。新建造的容量是先前的阵列,然后原始数组结束了,最后将颜色重组为false
在第一个大判断中,除非执行或或或或或或或或或off执行,否
实际上,它是为了更改价值,重新回到另一个较低的出价,并避免较低的出价。在方法的开头,为什么等于需要初始化的0,因为如果是0,则操作操作后,尴尬
如此疲倦,喝唾液,咕unt-----
此方法也很长。同样,有一些,有很多细节(笑),看一点,
这是为了确定每个线程,这是众所周知的。如果CPU核心大于1,则计算一个等于1的值,则设置范围是毫无意义的。
然后进入初始化操作
我不知道您是否已经注意到了,在这里,道格忘了吗?
显然不是,不是需要在这里锁定吗?如果同时存在操作,则方向的对象地址将会改变,这将发生。起初,Axuan在这里阅读。
我想,这里的操作是什么?后来,我转过了前后源代码,最后,哦-----------------------------------------------------------------------------------------------
来看看一起发生了什么
通过搜索,我了解到转移对总共有用
第二种方法是在putval中。如果节点的哈希值等于-1,那么很明显,这将通过
第三种方法,主要角色也是执行的。不同之处在于,该方法是要发现当链接列表变成红色和黑树时,它将转到此方法。
每个人都回想起,在说只有通过CAS的线程才能进入之前。其他线程输入。请注意。有一个非常不起眼的判断。也就是说,当其他线程提出此判断时,它将直接跳出周期。
因此,除了要输入的第一个线程外,其他线程必须输入传输,因此在传输方法中初始化
然后向下看,设置2个临时变量,然后执行一个死周期
当进入内部周期时,它将在第一次输入周期时,确定线程,然后在以后输入周期时转到第一个。当负责它的扩展范围(如果目前分配了所有间隔),则已分配。
接下来,有一个判断。当时,我小于0。如果目标索引位置的值是,则将CAS设置为
转发节点是一个简单的软件包,这意味着扩展后的数组数量数量
如果您找到节点,然后继续,在这里,每个人都想到,何时将执行该分支?从上面的循环中,如果被判断,这可能是什么?读者可以先思考,这将在后面提及
如果节点不是空的,则节点的值将在新数组上。如果您阅读了,它将很容易理解。我们计算数组中的中间和下投标。它是相同的,例如,n = 8,在扩展n = 16之后,转换为二进制
换句话说,扩展后数组的位置取决于数组的位置,并且位置为。如果n = 8,那个位置是8
计算节点,然后以分配值,例如,这是什么意思
如果计算了4,5,6,3个节点,则基于高引号和低级别参考的值,该节点表示更改,然后通过一个变化,位置会更改,并且不会更改位置。最终分配一个值
当所有数据完成后,我将成为,如果
当我第一次进入时,我进入了,因为我已经结束了,所以我必须通过它,当然,如果它失败了,请重新输入周期,如果if判断不陌生,请记住我们吗?判断该线程是否在此时。如果不是这样,退出方法,无论您是什么,否则,在这里看到,我怎么能相等?还记得开头中提到的条件,如果没有这样的条件,那么最后一个线程只会检查边界的间隔,但是在这种情况下,您将再次检查资本
当您第二次进入时,因为为了清酒,您将重新启动一些关键变量
还记得以前的问题,什么时候执行此情况?
是的,它将在
实际上,上次在Axuan中检查过,但是老人比较了,所以他再次检查了一下,然后Axuan检查了一波信息,发现有人真的问了道格关于这个问题。地址http:// cs.oswego.edu/pipermail/concurrency-iterest/2020-july/017171.html,doug
已更新。
词语中的含义也说,确实可以稍后完成
在阅读了该方法的整个静脉后,该方法要简单得多,因为它是通过修改进行修改的
因此,直接执行节点,如果您遇到的话,将其返回,如果您不这样做,则将其返回null。
最后查看计算设定容量的方法
它也很简单,也就是说,添加数组的值
通过对源代码的研究,我们发现作者使用了很多技能,值得我们。因此,当您没事的时候,您可以更多地关闭源代码。
原始:https://juejin.cn/post/7095579161401507853