[英]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.