底層數(shù)據(jù)結(jié)構(gòu): JDK1.7 的 ConcurrentHashMap 底層采用
分段數(shù)組+鏈表
實現(xiàn)寞肖,而 JDK1.8 的 ConcurrentHashMap 實現(xiàn)跟 HashMap1.8 的數(shù)據(jù)結(jié)構(gòu)一樣双藕,都是數(shù)組+鏈表/紅黑二叉樹
躲惰。Hashtable 和 JDK1.8 之前的 HashMap 的底層數(shù)據(jù)結(jié)構(gòu)類似,都是采用數(shù)組+鏈表
的形式睁宰。數(shù)組是 HashMap 的主體,鏈表則是為了解決哈希沖突而存在的;實現(xiàn)線程安全的方式: ① 在 JDK1.7 的時候爹土,ConcurrentHashMap(分段鎖) 對整個桶數(shù)組進(jìn)行了分割分段( Segment ),每一把鎖只鎖容器其中的一部分?jǐn)?shù)據(jù)踩身,這樣多線程訪問容器里不同數(shù)據(jù)段的數(shù)據(jù)胀茵,就不會存在鎖競爭,提高了并發(fā)訪問率挟阻。 到了 JDK1.8琼娘,摒棄了 Segment 的概念,而是直接用 Node 數(shù)組+鏈表+紅黑樹的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)附鸽,并發(fā)控制使用 synchronized 和 CAS 來操作脱拼,(JDK1.6 以后對 synchronized 鎖做了很多的優(yōu)化) 整個看起來就像是優(yōu)化過且線程安全的 HashMap,雖然在 JDK1.8 中還能看到 Segment 的數(shù)據(jù)結(jié)構(gòu)坷备,但是已經(jīng)簡化了屬性熄浓,只是為了兼容舊版本;② Hashtable (同一把鎖) :使用 synchronized 來保證線程安全省撑,效率非常低下赌蔑。一個線程訪問同步方法時,當(dāng)其他線程也訪問同步方法竟秫,可能會進(jìn)入阻塞或輪詢狀態(tài)娃惯,如使用 put 添加元素,另一個線程就不能使用 put 添加元素肥败,也不能使用 get趾浅,競爭會越來越激烈,效率就越低拙吉。
對比圖:
- Hashtable
- JDK1.7 的 ConcurrentHashMap
- JDK1.8 的 ConcurrentHashMap(TreeBin: 紅黑二叉樹節(jié)點潮孽;Node: 鏈表節(jié)點)