分段哈希映射。更多细分会增加还是降低表现?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分段哈希映射。更多细分会增加还是降低表现?相关的知识,希望对你有一定的参考价值。
我试图了解分段哈希映射的工作原理。我知道他们使哈希映射更安全,但是我不清楚分割数据是否会增加每秒可以在给定哈希映射上执行的操作的总数。
例如,如果我有一个包含10,000个元素的哈希映射并且逐渐增加了段的数量,那么我是否会看到程序的吞吐量和每秒操作的增加或减少?
concurrencyLevel参数在现代实现中没有任何作用,只存在以保持API与早期版本的JDK的兼容性,或者像Javadoc所说:
此外,为了与此类的先前版本兼容,构造函数可以选择将预期的
concurrencyLevel
指定为内部大小调整的附加提示。
它是implemented如下:
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel) {
if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
throw new IllegalArgumentException();
if (initialCapacity < concurrencyLevel) // Use at least as many bins
initialCapacity = concurrencyLevel; // as estimated threads
long size = (long)(1.0 + (long)initialCapacity / loadFactor);
int cap = (size >= (long)MAXIMUM_CAPACITY) ?
MAXIMUM_CAPACITY : tableSizeFor((int)size);
this.sizeCtl = cap;
}
也就是说,如果用户指定了一个不切实际的低concurrencyLevel
,initialCapacity
只会覆盖initialCapacity
。就这样。
而且,这仅仅设定了地图的初始容量;实际容量将随着条目的数量而增长(按照loadFactor
的指示)。
总而言之,concurrencyLevel
除了最模糊的用例之外都没有持久的影响(一个具有错误指定的初始容量的映射包含的条目少于访问它的线程,并且由于所有线程大部分时间都与该映射交互而受到严重争议) 。
你还问:
由于每个细分市场本质上都是一个锁,当然更多的细分市场会减慢程序,因为这意味着一些方法和操作必须等待?
要获取或放置值,线程将仅锁定包含它的段。也就是说,将映射划分为更多段不会导致在每个操作中获取或释放更多锁,但会降低锁争用的可能性,因为每个段的条目较少。
此外,值得注意的是ConcurrentHashMap中的许多方法都是等待的。例如,以下是获取值的方法:
public V get(Object key) {
Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
int h = spread(key.hashCode());
if ((tab = table) != null && (n = tab.length) > 0 &&
(e = tabAt(tab, (n - 1) & h)) != null) {
if ((eh = e.hash) == h) {
if ((ek = e.key) == key || (ek != null && key.equals(ek)))
return e.val;
}
else if (eh < 0)
return (p = e.find(h, key)) != null ? p.val : null;
while ((e = e.next) != null) {
if (e.hash == h &&
((ek = e.key) == key || (ek != null && key.equals(ek))))
return e.val;
}
}
return null;
}
以上是关于分段哈希映射。更多细分会增加还是降低表现?的主要内容,如果未能解决你的问题,请参考以下文章