ConcurrentHashMap介绍
ConcurrentHashMap
ConcurrentHashMap底層原理:
ConcurrentHashMap底層數(shù)據(jù)結(jié)構(gòu)和HashMap差不多 ,而在產(chǎn)生Hash沖突時使用synchronized加鎖來 和CAS模式來保證線程的安全!
CAS + synchronized + Node + 紅黑樹ConcurrentHashMap的重要屬性:
private transient volatile int sizeCtl; 當sizeCtl當為負數(shù)時,-1 表示正在初始化,-N 表示 N - 1 個線程正在進行擴容;當為 0 時,表示 table 還沒有初始化;當為其他正數(shù)時,表示初始化或者下一次進行擴容的大小。構(gòu)造器:
initialCapacity:表示數(shù)組容量 loadFactor 加載因子 concurrencyLevel最大線程 底層保證了initialCapacity>=concurrencyLevel并且 loadFactor是2的次方倍。
并發(fā)度:程序運行時能夠同時更新 ConccurentHashMap 且不產(chǎn)生鎖競爭的最大線程數(shù)。默認為 16,且可以在構(gòu)造函數(shù)中設(shè)置。當用戶設(shè)置并發(fā)度時,ConcurrentHashMap 會使用大于等于該值的最小2冪指數(shù)作為實際并發(fā)度(假如用戶設(shè)置并發(fā)度為17,實際并發(fā)度則為32)
put() 方法
流程:
1、如果沒有初始化,就調(diào)用 initTable() 方法來進行初始化; 2、如果沒有 hash 沖突就直接 CAS 無鎖插入; 3、如果需要擴容,就先進行擴容; 4、如果存在 hash 沖突,就加鎖來保證線程安全,兩種情況:一種是鏈表形式就直接遍歷到尾端插入,一種是紅黑樹就按照紅黑樹結(jié)構(gòu)插入; 5、如果該鏈表的數(shù)量大于閥值 8,就要先轉(zhuǎn)換成紅黑樹的結(jié)構(gòu),break 再一次進入循環(huán) 6、如果添加成功就調(diào)用 addCount() 方法統(tǒng)計 size,并且檢查是否需要擴容。擴容機制:
擴容時機:
(1) 元素個數(shù)達到擴容閾值。 (2) 調(diào)用 putAll 方法,但目前容量不足以存放所有元素時。 (3) 某條鏈表長度達到8,但數(shù)組長度卻小于64時。 注意:桶上鏈表長度達到 8 個或者以上,并且數(shù)組長度為 64 以下時只會觸發(fā)擴容而不會將鏈表轉(zhuǎn)為紅黑樹 。擴容過程:
構(gòu)建一個nextTable,大小為table的兩倍。 把table的數(shù)據(jù)復(fù)制到nextTable中。 注意:在復(fù)制過程支持多線程復(fù)制Hashtable和 ConcurrentHashMap的區(qū)別:
hashtable和ConcurrentHashMap都是線程安全的 ,但是Hashtable是通過在修改數(shù)據(jù)時鎖住整個HashTable,效率較低 而ConcurrentHashMap是通過原子性的操作保證數(shù)據(jù)的讀取安全,然后再通過發(fā)生Hash沖突一個給這個數(shù)組位置加鎖,鎖的力度較小來保證 高并發(fā)下的線程安全的,而且他的擴容也是支持多線程擴容的,效率較高,Java5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴展性更好。
總結(jié)
以上是生活随笔為你收集整理的ConcurrentHashMap介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IO流之过滤流介绍:
- 下一篇: MYSQL事务特点