并发HashMap Null键和并发级别

时间:2015-08-13 14:33:25

标签: java multithreading concurrency hashmap

有人可以为以下问题提供答案:

  1. 我理解null中不允许ConcurrentHashMap 的原因。但是为什么不允许null

  2. 并发级别确定可以并发访问映射的线程数,默认值为16.这意味着映射分为16个部分,并且每个部分都放置了锁。只要初始容量也是16,这样工作正常,因此有16个桶和16个锁,每个桶可以锁定一个锁。 当初始容量大于并发级别时以及初始容量小于并发级别时,它如何工作?

3 个答案:

答案 0 :(得分:1)

  1. 为什么在ConcurrentHashMaps中不允许null个键? HashMap从Object.hash()获取其内部键,无法为空值计算。为了解决这个问题,非并发HashMaps将null映射到哈希码0.为了在ConcurrentHashMap中解决这个问题,应该可以牺牲性能。
  2. 检查ConcurrentHashMap的实现:即使你试图将initalCapacity设置为某个东西,它也会进行自己的内部计算,所以这些参数都是提示。

答案 1 :(得分:1)

  

[...]地图分为16个部分,并在每个部分上放置锁定。只要初始容量也是16,这样就可以正常工作,因此有16个桶和16个锁,每桶可以锁定一个锁。

为什么假设16个线程中的每一个都想要访问不同的存储桶?如果他们都想要访问相同的存储桶怎么办?

不要将其视为16个不同的存储桶,将其视为16个完全不同的子表。散列k.hashCode()不仅确定密钥k所属的表的哪个桶,还确定在哪个子表中。

如果两个线程对两个不相关的密钥jk感兴趣,那么密钥属于不同子表的概率为15/16,并且线程可以访问表没有争用。另外1/16的时间,这是艰难的运气,其中一个线程将不得不等待;但这比他们100%碰撞的情况要好得多。

答案 2 :(得分:0)

问题1 我想一般来说支持null密钥是可能的。但这会对可读性产生影响,并可能对性能产生一点影响。后者与提供高性能多线程地图实现的目标相冲突。

问题2 如果初始容量小于预期的并发级别,则将初始容量调整为访问Map(initialCapacity = concurrencyLevel)的估计线程数。除此之外,对ConcurrentHashMap的并发访问在很大程度上与容量无关,因为线程会在访问时锁定整个存储桶(更具体地说,它们会锁定存储桶中的第一个元素)。