Java 并发HashMap空键和并发级别
请有人回答以下问题:Java 并发HashMap空键和并发级别,java,multithreading,concurrency,hashmap,Java,Multithreading,Concurrency,Hashmap,请有人回答以下问题: 我理解ConcurrentHashMap中不允许null值的原因。但是为什么不允许使用null键呢 并发级别决定有多少线程可以并发访问映射,默认值为16。这意味着地图分为16个部分,每个部分都有锁。只要初始容量也是16,这就可以正常工作,因此有16个铲斗和16个锁,每个铲斗工作一个锁。 当初始容量大于并发级别时,以及初始容量小于并发级别时,这是如何工作的 为什么ConcurrentHashMaps中不允许使用null键?HashMap从Object.hash()获取其内部键
ConcurrentHashMap
中不允许null
值的原因。但是为什么不允许使用null
键呢null
键?HashMap从Object.hash()获取其内部键,该值不能为空值计算。为了解决此问题,非并发哈希映射将null映射到哈希代码0。为了在ConcurrentHashMap
中解决此问题,可能需要牺牲性能问题1 我想支持
null
键通常是可能的。但这会对可读性产生影响,可能会对性能产生一些影响。后者与提供高性能多线程映射实现的目标相冲突
问题2如果初始容量小于预期的并发级别,则初始容量将调整为访问映射的估计线程(initialCapacity=concurrencyLevel
)。除此之外,并发访问ConcurrentHashMap
在很大程度上与容量无关,因为线程在访问时锁定整个存储桶(更具体地说,它们锁定存储桶中的第一个元素)
[…地图分为16个部分,每个部分都有锁。只要初始容量也是16,这就可以正常工作,因此有16个铲斗和16个锁,每个铲斗工作一个锁
为什么假设16个线程中的每一个都希望访问不同的存储桶?如果他们都想访问同一个存储桶呢
不要把它想象成16个不同的桶,把它想象成16个完全不同的子表。散列,k.hashCode()
,不仅确定键k
属于表的哪个存储桶,还确定键属于哪个子表
如果两个线程对两个不相关的键感兴趣,
j
和k
,那么这些键属于不同子表的概率为15/16,并且线程可以访问这些表而不存在争用。另1/16的时间,这是艰难的运气,其中一个线程将不得不等待;但这比它们100%碰撞的情况要好得多。问题1在这里得到了回答:@Keppil不,只有null
values.Hmm的答案。答案的第一部分提到并发映射中的null
,但示例仅使用null
作为值。然而,原始链接的答案也是关于键和值的问题,因此我将第一部分关于歧义的解释为这两个问题的原因。@Keppil如果我们有空值,您能详细说明一下歧义是什么吗key@Keppil不支持null
值的参数(歧义)易于理解-与null
键相比。我的猜测是,实际上没有具体的原因。HashMap
允许null
作为键,而ConcurrentHashMap
则不允许。@Andrei我认为,OP的问题是关于设计决策:作者为什么不想要null键?很明显,如果ConcurrentHashMap的创建者希望允许null,那么NPE就有了某种解决方案。(1)对象。自Java7以来,hash()返回0
fornull
@steffen对象
(而不是对象
)。旧版本也没有,因此必须调用object.hash()
。HashMap的实现确实将null匹配到哈希键0。短语“我猜”和“可能有一点”使人不清楚这是一个答案还是一个暗中猜测。@jaco0646虽然源代码包含大量关于null
值含义的注释,关于null
键没有任何内容,只是它们不受支持!我认为所有关于映射键的代码都可以处理null
,特别是因为它们被包装在节点
实例中。这个类包含大约6000行,我没有和作者交谈,所以我不知道他为什么决定不支持null
键。因此,我想写作是我能做的最精确的事情。