[英]Segmented Hash Maps. Do more segments increase or decrease performance?
我试图了解分段哈希图的工作方式。 我知道它们使哈希图更加线程安全,但是对于将数据划分为段是否会增加每秒可在给定哈希图上执行的操作总数,我尚不清楚。
例如,如果我有一个包含10,000个元素的哈希图并逐渐增加了段数,那么我会发现程序的吞吐量和每秒的操作增加还是减少?
concurrencyLevel参数在现代实现中无效,仅存在是为了保持API与早期版本的JDK的兼容性,或者如Javadoc所说的那样:
另外,为了与此类的早期版本兼容,构造函数可以选择指定期望的
concurrencyLevel
作为内部调整的附加提示。
它的实现如下:
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.