在ConcurrentHashMap中如何定义段

时间:2016-10-12 11:34:17

标签: java multithreading concurrency concurrenthashmap

朋友您好我是Java Concurrency的新手。我有两个问题如下。

Q.1在ConcurrentHashMap中如何定义段?意味着如果Map中的64个元素和concurrencyLevel值为16(有16个线程可以同时工作)那么这些段是如何定义的?问题是它们是相同大小的16个段,每个段有4个元素吗?或者它将是不等大小的片段?

Q.2。如果我定义ConcurrentHashMap,初始容量为62,concurrencyLevel为16.如果我在该映射中放入62个元素。根据我的理解,将有15个段,每个段有4个元素,第16段有2个元素?我在这里纠正吗?

提前致谢

3 个答案:

答案 0 :(得分:1)

考虑ConcurrentHashMap的实现,它们使用段(不是全部),因为它基本上是一个两级哈希表。给定密钥K和密钥h = K.hashCode()的哈希码,您首先使用h哈希到16个段的数组中,就像普通哈希映射一样(例如,通过{ {1}}或类似的东西)。这会为您提供密钥所在的细分,这只是另一个地图 - 再次使用h % 16在此地图中查找密钥。

不同之处在于,任何锁定操作(通常在h等变异操作期间发生)只需要锁定所涉及的段,因此其他操作有可能并行进行。

具体回答您的问题:

<强> Q1

这些段的容量大小相同,但它们通常具有不等数量的元素,因为元素的段是使用散列选择的,除非在特殊情况下,否则不会导致完全均匀。它就像你询问put()中支持的前半部分是否与后半部分具有相同数量的元素一样。在平均 期望的元素数量是相同的,但对于任何给定的HashMap,它与完全高度不同>由于随机变化,两半中的元素数量相同。

<强> Q2

不,地图不会像那样布局。如上所述,使用散列来完成将元素选择成片段,这意味着(对于良好的散列函数),片段基本上是随机选择的。想象一下,你有一个标记为1到16的球,你一次选择一个球,62次,并记录你在更换球之前得到的数字。你不会期望获得像HashMap这样的发行版!它会更随机。

答案 1 :(得分:0)

Q.1在ConcurrentHashMap中如何定义段?意味着如果Map中的64个元素和concurrencyLevel值为16(有16个线程可以同时工作)那么这些段是如何定义的?问题是它们是相同大小的16个段,每个段有4个元素吗?或者它是不等大小的片段?

ANS - 如果您将16定义为并发级别,那么将创建16个分段。

每个段内部维护HashTable S [0] - &gt;哈希表()。

因此,如果您有64个元素,那么每个元素Hash(Key)将计算分段编号,您可能拥有所有不同大小的分段。段哈希码的计算方式是它将返回(0-15)之间的任何数字。

<强> Q.2。如果我定义ConcurrentHashMap,初始容量为62,concurrencyLevel为16.如果我在该映射中放入62个元素。根据我的理解,将有15个段,每个段有4个元素,第16段有2个元素?我在这里纠正吗?

ANS-如上所述,每个段的选择都是基于计算的哈希码完成的,因此不能确定所有16段都具有相同的大小。

答案 2 :(得分:0)

这里有一些计算逻辑,可以帮助您在构造ConcurrentHashMap时计算段的数目以及每个段中HashTable的大小。

  1. 如果并发级别为16,则预期的段数将不是-

    2^n => concurrency level.
    
    i.e 2^4 >= 16
    
    16 => 16 Hence 16 segments will be created.
    
    Similarly if concurrency level is 10 then
    
    Segment array size would be 2^n => 10 i.e 2^4 => 10
    Segment array size is 16
    
    another example - if concurrency level is 8 then 
    segment size = 2^n => 8 i.e 2^3=> 8
    hence segment size will be 8.
    
  2. 计算每个细分下的HashTable的大小-

    HashEntry[] array size = 2 ^ x ≥ (initialCapacity / concurrencyLevel)
    
    Example - 
    
    ConcurrentHashMap map = new ConcurrentHashMap(64, 0.75f, 8)
    HashEntry[] array size = 2^n ≥ 64/8 => 2^3 ≥ 8
    Hence, HashEntry[] array size will be 8.
    
    Also Segment size will be = 2^n ≥ 8 => 8.