如何保證容器是線程安全的?ConcurrentHashMap 如何實現高效地線程安全?

《Java核心技術面試精講–楊曉峯》學習筆記目錄

不好意思,我併發幾乎沒學,這章沒法看,記一下基礎知識吧

回答

Java 提供了不同層面的線程安全支持。在傳統集合框架內部,除了Hashtable等同步容器,還提供了所謂的同步包裝器(Synchronized Wrapper),我們可以調用Collections工具類提供的包裝方法,來獲取一個同步的包裝容器(如Collections.synchronizedMap),但是它們都是利用非常粗粒度的同步方式,在高併發情況下,性能比較低下。

另外,更加普遍的選擇是利用併發包提供的線程安全容器類,它提供了:

  • 各種併發容器,比如 ConcurrentHashMapCopyOnWriteArrayList
  • 各種線程安全隊列(Queue/Deque),如 ArrayBlockingQueueSynchronousQueue
  • 各種有序容器的線程安全版本等。

具體保證線程安全的方式,包括有從簡單的synchronize方式,到基於更加精細化的,比如基於分離鎖實現的ConcurrentHashMap等併發實現等。具體選擇要看開發的場景需求,總體來說,併發包內提供的容器通用場景,遠優於早期的簡單同步實現。

ConcurrentHashMap和Hashtable的區別

ConcurrentHashMap和Hashtable的區別主要體現在實現線程安全的方式上不同。

  • 底層數據結構: JDK1.8採用的數據結構跟HashMap1.8的結構- -樣,數組+鏈表/紅黑二叉樹。Hashtable和JDK1.8之前的HashMap的底層數據結構類似都是採用數組+鏈表的形式,數組是HashMap的主體,鏈表則是主要爲了解決哈希衝突而存在的;
  • 實現線程安全的方式(重要) :JDK1.8Node數組+鏈表+紅黑樹的數據結構來實現,併發控制使用synchronizedCAS來操作。(JDK1.6以後對synchronized鎖做了很多優化)整個看起來就像是優化過且線程安全的HashMap,Hashtable(同一把鎖) :使用synchronized來保證線程安全,效率非常低下。當一個線程訪問同步方法時,其他線程也訪問同步方法,可能會進入阻塞或輪詢狀態,如使用put添加元素,另一個線程不能使用put添加元素,也不能使用get,競爭會越來越激烈效率越低。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章