8

我读到 ConcurrentHashMap 在多线程中比 Hashtable 工作得更好,因为在存储桶级别有锁而不是映射范围的锁。每张地图最多可以有 32 个锁。想知道为什么是32个,为什么不超过32个锁。

4

4 回答 4

9

如果您在谈论 Java ConcurrentHashMap,那么限制是任意的:

创建一个与给定地图具有相同映射的新地图。映射的容量是给定映射中映射数量的 1.5 倍或 16(以较大者为准),默认负载因子 (0.75) 和并发级别 (16)。

如果您阅读源代码,就会清楚最大段数为 2^16,这对于近期任何可以想象的需求应该绰绰有余。

您可能一直在考虑某些替代实验性实现,例如

此类支持硬连线预设并发级别 32。这允许最多 32 个 put 和/或 remove 操作同时进行。

请注意,一般来说,当超过 32 个线程尝试更新单个ConcurrentHashMap.

于 2009-11-22T15:47:03.610 回答
5

默认不是 32,而是 16。您可以使用构造函数参数concurrency level覆盖它:

public ConcurrentHashMap(int initialCapacity,
                         float loadFactor,
                         int concurrencyLevel)

所以你可以这样做:

Map<String, String> map = new ConcurrentHashmap<String, String)(128, 0.75f, 64);

将其更改为 64。默认值为(从 Java 6u17 开始):

  • initialCapacity: 16;
  • loadFactory: 0.75f;
  • concurrencyLevel: 16。
于 2009-11-22T15:42:32.683 回答
3

根据 的来源ConcurrentHashMap,允许的最大值为65536

/**
 * The maximum number of segments to allow; used to bound
 * constructor arguments.
 */
static final int MAX_SEGMENTS = 1 << 16; // slightly conservative

public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel) {
    if (concurrencyLevel > MAX_SEGMENTS)
        concurrencyLevel = MAX_SEGMENTS;
于 2009-11-22T15:51:34.323 回答
2

要使用所有默认的 16 并发级别,您需要有 16 个内核同时使用映射。如果您有 32 个核心仅在 25% 的时间内使用映射,那么一次将仅使用 16 个段中的 8 个。

总而言之,你需要有很多核心都使用同一张地图,并且什么都不做。真正的程序通常会做一些事情,而不是访问一张地图。

于 2009-11-29T09:52:13.903 回答