3

我已经阅读了ConcurrentHashmap来自不同来源的一些声明,并想验证它们是否确实如此。

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

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

4

3 回答 3

2

迭代器在编辑/删除后是否刷新其快照?为什么迭代器对待更新/删除与添加有任何不同。

在 API 中解释了 CHM 的迭代器,这样

类似地,迭代器和枚举返回反映哈希表在创建迭代器/枚举时或之后的某个时间点的状态的元素。

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

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

那么为什么并发级别会影响内存呢?

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

Java 8 是CHMv8版本,它实际上解决了这个问题。

您可以在此处阅读有关内存的更多信息,特别是:

在进行内存分析时,JVisualVM 表明最大的罪魁祸首是 ConcurrentHashMap.Segment 类。每个 ConcurrentHashMap 的默认段数是 16。段内的 HashEntry 表可能很小,但每个段都是一个 ReentrantLock。每个 ReentrantLock 都包含一个 Sync,在本例中是一个 NonFairSync,它是 Sync 和 AbstractQueuedSynchronizer 的子类。其中每一个都包含一个节点队列,这些节点维护线程正在发生的事情的状态。它在确定公平性时使用。该队列和节点使用大量内存。

于 2013-04-08T18:06:24.010 回答
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 字节。)

于 2013-04-08T18:07:33.567 回答
0

请记住,哈希表只是其核心的一个数组,它具有一些巧妙的功能,允许您使用非整数键并仍然获得恒定的时间访问。

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

  2. 通常,在这种情况下,分片意味着地图被分割成一定数量的子数组,因此您一次不太可能命中多个子数组。如果您指定较少数量的分片,实际上对于大多数实例来说更好,2 通常就足够了,除非您在该表上存在大量争用的服务器上运行。也可以看看:

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

于 2013-04-08T18:03:44.337 回答