关于Concurrenthashmap的事实

时间:2013-04-08 17:51:00

标签: java concurrenthashmap

我已经阅读了来自不同来源的ConcurrentHashmap的几个陈述,并想验证它们是否真的如此。

  1. 创建ConcurrentHashmap的迭代器后,只保证反映线程的删除和更新操作。 迭代器是否在编辑/删除后刷新其快照?为什么迭代器会以与ADD不同的方式处理更新/删除。

  2. ConcurrentHashmap将其数据分段为段以减少写入程序锁争用。 concurrencyLevel参数直接指定类内部创建的分片数。 如果我们只使用无参数构造函数并接受默认配置,那么在您添加第一个值之前,地图将实例化16个分片所需的对象... 碎片在这里是什么意思?它是地图中的一桶数据 - 还是整个地图的副本。 我理解这与数据库中的一个页面类似,可以独立锁定毛发更新。 为什么concurrencyLevel会影响记忆?

3 个答案:

答案 0 :(得分:2)

  

迭代器是否在编辑/删除后刷新其快照?为什么会这样?   迭代器以与ADD不同的方式处理更新/删除。

CHM的迭代器在API中解释为

  

同样,Iterators和Enumerations返回反映的元素   在创建时的某个时刻或者自创建之后的哈希表的状态   迭代器/枚举。

意味着返回的迭代器可能会也可能不会反映迭代时Map中发生的更改。想象一下,如果您创建迭代器并遍历整个段并转到下一个段。在您转到下一个段后,您完成遍历的第一个段已完成添加或删除。好吧,你不会看到那个,没关系,它没有违反API。

关于你的第二个问题。暗示添加,添加和删除之间的可见性没有区别。

  

为什么concurrencylevel会影响内存呢?

自发布以来,内存一直是ConcurrentHashMap的一个问题。默认情况下,每个级别的并发都会创建一个Segment。这个段有一个HashEntry表,也是一个Reentrant锁(所以它的所有必需品)。

Java 8是发布CHMv8,实际上解决了这个问题。

您可以在内存here上阅读更多内容,特别是:

  

在进行内存配置文件时,JVisualVM显示了最重要的罪魁祸首   是ConcurrentHashMap.Segment类。默认数量   ConcurrentHashMap的段数为16.内的HashEntry表   段可能很小,但每个段都是一个ReentrantLock。   每个ReentrantLock都包含一个Sync,在本例中为NonFairSync   是Sync的子类,然后是AbstractQueuedSynchronizer。每个   这些包含维护状态的节点队列   与你的线程发生。在确定公平性时使用它。   此队列和节点使用大量内存。

答案 1 :(得分:1)

  1. 如果您指的是entrySet枚举,这将(最终)反映对父对象执行的添加和删除操作。但是,枚举本身不支持添加操作。

  2. 在这种情况下,分片本质上是哈希表的哈希表。假设ConcurrentHashMap的后备数组包含1024个条目。如果没有分片,这意味着对象的散列值将映射到[0,1023]之间的整数。使用分片这意味着后备阵列包含16个64个条目的后备阵列,即[0,1023]后备阵列现在是来自[0,63]的阵列,另一个阵列来自[64,127]等。让我们说你'修改哈希值为100的对象 - 没有分片你将锁定整个[0,1023]后备阵列,但是使用分片你只能锁定[64,127]子阵列,允许其他线程修改其他碎片。您拥有的分片越多,ConcurrentHashMap的并发性就越大,但是您拥有的分片越多,维护它们所需的内存就越多。 (然而,这不是乘法效应,使用16个分片会乘以16使用的内存总量。相反,它是一个加性效应;假设需要64个字节来维护每个分片的数据结构,因此使用16个分片向数据结构添加1024个字节,使用64个分片将4096个字节添加到数据结构中。)

答案 2 :(得分:0)

请记住,哈希表只是一个核心的数组,有一些聪明,允许你使用非整数键,并且仍然可以获得恒定的时间访问。

  1. 对于添加,添加元素可能会导致哈希表增长,从而创建新的基础数组并重新排序表的元素。散列的迭代器可能会指向旧数组,因此它可以保持其位置。

  2. 通常,在此上下文中进行分片意味着将地图拆分为若干个子数组,这样您就不可能一次击中多个子数组。实际上,如果指定较少数量的分片,对于大多数实例来说实际上更好,除非您在该表上存在大量争用的服务器上运行,否则2通常就足够了。另见:

  3. http://ria101.wordpress.com/2011/12/12/concurrenthashmap-avoid-a-common-misuse/

相关问题