concurrenthashmap是一種執行緒安全的hashmap,相對於hashtable, 它擁有更高的併發性.
現在,我們就來分析一下在jdk1.8下的concurrenthashmap的實現及原理:
public v get(object key)
//hash值為負值表示正在擴容,這個時候查的是forwardingnode的find方法來定位到nexttable來
//eh=-1,說明該節點是乙個forwardingnode,正在遷移,此時呼叫forwardingnode的find方法去nexttable裡找。
//eh=-2,說明該節點是乙個treebin,此時呼叫treebin的find方法遍歷紅黑樹,由於紅黑樹有可能正在旋轉變色,所以find裡會有讀寫鎖。
else if (eh < 0)
//eh>=0,說明該節點下掛的是乙個鍊錶,直接遍歷該鍊錶即可。
while ((e = e.next) != null)
}return null;//未找到對應的值
}
可以看到,在1.8中concurrenthashmap的get操作全程不需要加鎖,這也是它比其他併發集合比如hashtable、用collections.synchronizedmap()包裝的hashmap;安全效率高的原因之一。
concurrenthashmap的get操作為什麼不需要加鎖呢?
大家都知道,執行緒安全常常是因為獲取的共享變數不一致而導致的,而get方法中訪問到的共享變數只有node型別的陣列table,
transient volatile node table;
而volatile關鍵字可以保證共享變數的可見性, 即實時訪問到其他執行緒修改後的資料. 那麼,get方法不加鎖的原因是因為table變數使用了volatile修飾麼, 其實不然, volatile關鍵字對於基本型別的修改可以在隨後對多個執行緒的讀保持一致, 但是對於引用型別如陣列,實體bean,僅僅保證引用的可見性,但並不保證引用內容的可見性。
真正的原因是因為在node類中val變數和next變數是用volatile修飾了, 也是因為此處保證了concurrenthashmap的get方法的執行緒安全
static class nodeimplements map.entry
由以上可以看出
get操作全程不需要加鎖是因為node的成員val是用volatile修飾的和陣列用volatile修飾沒有關係。
陣列用volatile修飾主要是保證在陣列擴容的時候保證可見性。
那麼, node陣列table為什麼要用volatile修飾呢?
其實就是為了使得node陣列在擴容的時候對其他執行緒具有可見性而加的volatile
final v putval(k key, v value, boolean onlyifabsent)
//hash桶(tab[i])是fwd節點,表示正在擴容
else if ((fh = f.hash) == moved)
//擴容
tab = helptransfer(tab, f);
else
nodepred = e;
//遍歷鍊錶,向尾結點插入資料
if ((e = e.next) == null) }}
//紅黑樹
else if (f instanceof treebin) }}
}if (bincount != 0) }}
//雜湊桶儲存的元素個數+1
addcount(1l, bincount);
return null;
}
從原始碼中看出,put方法在往空的雜湊桶新增元素時,是採用cas演算法無鎖插入的; 只有在發生雜湊碰撞時,才會給雜湊桶加上鎖,鎖是每個雜湊桶的頭結點.
public v remove(object key)
/*** implementation for the four public remove/replace methods:
* replaces node value with v, conditional upon match of cv if
* non-null. if resulting value is null, delete.
* * 四個公共刪除/替換方法的實現:用v替換節點值,條件是如果非空則匹配cv。如果結果值為null,請刪除。
* */
final v replacenode(object key, v value, object cv)
break;
}pred = e;
if ((e = e.next) == null)
break;}}
//紅黑樹
else if (f instanceof treebin) }}
}}if (validated)
break;}}
}return null;
}
remove方法也是鎖住雜湊桶的頭結點.依賴於cas算 輕鬆理解EJB
昨天給乙個班講jsp,那個班已經把所有的技術都學完了,但是學的不好,那個學校讓我過去快速的重講一遍,真的很累,這些學生也很令人感到,他們除了聽我的課,還插班聽其他老師的課,上午我聽說他們剛剛聽別的老師講ejb很暈,我決定臨時調整授課內容,給他們講清楚ejb。ejb難點在多個檔案,他們的作用是什麼?如...
輕鬆理解 Fisher判別
以前看費舍爾判別,老是看一點就看不下去,今天耐著性子看完後,發現這個東西真的是很神奇,而且是線性判別,最後只要計算乙個向量乘法和減法,然後比較最小值就能解決判別問題,下面用例子講比較好理解,我們來判斷乙個東西是人,猴,豬,狗?四個總體,可以包含幾個分量,比如重量,身高,智商,情商這四個分量,所以現在...
輕鬆理解KMP演算法
字串匹配 是計算機的基本任務之一。舉例來說,有乙個字串 bbc abcdab abcdabcdabde 我想知道,裡面是否包含另乙個字串 abcdabd 許多演算法可以完成這個任務,knuth morris pratt演算法 簡稱kmp 是最常用的之一。它以三個發明者命名,起頭的那個k就是著名科學家...