ConcurrentHashMap和HashMap,HashTable的區別

1.爲什麼要使用ConcurrentHashMap

由於HashMap的線程不安全:HashMap多線程死循環問題,在多線程環境下並不會使用HashMap,雖然HashTable是線程安全的,但是它的類似put,get方法都是Synchronized修飾的,併發效率十分低下,在這個時候就需要用到ConcurrentHashMap來解決併發條件下HashTable效率低下的問題了
ConcurrentHashMap在jdk1.7和jdk1.8中的不同

2.HashMap 和 ConcurrentHashMap 的區別

  • ConcurrentHashMap對整個桶數組進行了分割分段(Segment),然後在每一個分段上都用lock鎖進行保護,相對於HashTable的synchronized鎖的粒度更精細了一些,併發性能更好,而HashMap沒有鎖機制,不是線程安全的。(JDK1.8之後ConcurrentHashMap啓用了一種全新的方式實現,利用CAS算法。)
  • HashMap的鍵值對允許有null,但是ConCurrentHashMap都不允許。

3.ConcurrentHashMap 和 Hashtable 的區別

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

  • 底層數據結構: JDK1.7的 ConcurrentHashMap 底層採用 分段的數組+鏈表 實現,JDK1.8 採用的數據結構跟HashMap1.8的結構一樣,數組+鏈表/紅黑二叉樹。Hashtable 和 JDK1.8 之前的 HashMap 的底層數據結構類似都是採用 數組+鏈表 的形式,數組是 HashMap 的主體,鏈表則是主要爲了解決哈希衝突而存在的;
  • 實現線程安全的方式
    • ① 在JDK1.7的時候,ConcurrentHashMap(分段鎖) 對整個桶數組進行了分割分段(Segment),每一把鎖只鎖容器其中一部分數據,多線程訪問容器裏不同數據段的數據,就不會存在鎖競爭,提高併發訪問率。(默認分配16個Segment,比Hashtable效率提高16倍。) 到了 JDK1.8 的時候已經摒棄了Segment的概念,而是直接用 Node 數組+鏈表+紅黑樹的數據結構來實現,併發控制使用 synchronized 和 CAS 來操作。(JDK1.6以後 對 synchronized鎖做了很多優化) 整個看起來就像是優化過且線程安全的 HashMap,雖然在JDK1.8中還能看到 Segment 的數據結構,但是已經簡化了屬性,只是爲了兼容舊版本;
    • ② Hashtable(同一把鎖) :使用 synchronized 來保證線程安全,效率非常低下。當一個線程訪問同步方法時,其他線程也訪問同步方法,可能會進入阻塞或輪詢狀態,如使用 put 添加元素,另一個線程不能使用 put 添加元素,也不能使用 get,競爭會越來越激烈效率越低。
      HashTable:
      在這裏插入圖片描述
      JDK1.7的ConcurrentHashMap:

在這裏插入圖片描述
JDK1.8的ConcurrentHashMap(TreeBin: 紅黑二叉樹節點 Node: 鏈表節點):
在這裏插入圖片描述

4.ConcurrentHashMap 底層具體實現知道嗎?實現原理是什麼?

JDK7:
首先將數據分爲一段一段的存儲,然後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個段數據時,其他段的數據也能被其他線程訪問。

在JDK1.7中,ConcurrentHashMap採用Segment + HashEntry的方式進行實現,結構如下:

一個 ConcurrentHashMap 裏包含一個 Segment 數組。Segment 的結構和HashMap類似,是一種數組和鏈表結構,一個 Segment 包含一個 HashEntry 數組,每個 HashEntry 是一個鏈表結構的元素,每個 Segment 守護着一個HashEntry數組裏的元素,當對 HashEntry 數組的數據進行修改時,必須首先獲得對應的 Segment的鎖。

  • 該類包含兩個靜態內部類 HashEntry 和 Segment ;前者用來封裝映射表的鍵值對,後者用來充當鎖的角色;
  • Segment 是一種可重入的鎖 ReentrantLock,每個 Segment 守護一個HashEntry 數組裏得元素,當對 HashEntry 數組的數據進行修改時,必須首先獲得對應的 Segment 鎖。
    在這裏插入圖片描述
    JDK8:
    在JDK1.8中,放棄了Segment臃腫的設計,取而代之的是採用Node + CAS + Synchronized來保證併發安全進行實現,synchronized只鎖定當前鏈表或紅黑二叉樹的首節點,這樣只要hash不衝突,就不會產生併發,效率又提升N倍。
    在這裏插入圖片描述
    參考博客:https://thinkwon.blog.csdn.net/article/details/104588551
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章