底層數(shù)據(jù)結(jié)構(gòu): JDK1.7 的 ConcurrentHashMap 底層采用
分段數(shù)組+鏈表實(shí)現(xiàn),而 JDK1.8 的 ConcurrentHashMap 實(shí)現(xiàn)跟 HashMap1.8 的數(shù)據(jù)結(jié)構(gòu)一樣,都是數(shù)組+鏈表/紅黑二叉樹(shù)。Hashtable 和 JDK1.8 之前的 HashMap 的底層數(shù)據(jù)結(jié)構(gòu)類似,都是采用數(shù)組+鏈表的形式。數(shù)組是 HashMap 的主體,鏈表則是為了解決哈希沖突而存在的;實(shí)現(xiàn)線程安全的方式: ① 在 JDK1.7 的時(shí)候,ConcurrentHashMap(分段鎖) 對(duì)整個(gè)桶數(shù)組進(jìn)行了分割分段( Segment ),每一把鎖只鎖容器其中的一部分?jǐn)?shù)據(jù),這樣多線程訪問(wèn)容器里不同數(shù)據(jù)段的數(shù)據(jù),就不會(huì)存在鎖競(jìng)爭(zhēng),提高了并發(fā)訪問(wèn)率。 到了 JDK1.8,摒棄了 Segment 的概念,而是直接用 Node 數(shù)組+鏈表+紅黑樹(shù)的數(shù)據(jù)結(jié)構(gòu)來(lái)實(shí)現(xiàn),并發(fā)控制使用 synchronized 和 CAS 來(lái)操作,(JDK1.6 以后對(duì) synchronized 鎖做了很多的優(yōu)化) 整個(gè)看起來(lái)就像是優(yōu)化過(guò)且線程安全的 HashMap,雖然在 JDK1.8 中還能看到 Segment 的數(shù)據(jù)結(jié)構(gòu),但是已經(jīng)簡(jiǎn)化了屬性,只是為了兼容舊版本;② Hashtable (同一把鎖) :使用 synchronized 來(lái)保證線程安全,效率非常低下。一個(gè)線程訪問(wèn)同步方法時(shí),當(dāng)其他線程也訪問(wèn)同步方法,可能會(huì)進(jìn)入阻塞或輪詢狀態(tài),如使用 put 添加元素,另一個(gè)線程就不能使用 put 添加元素,也不能使用 get,競(jìng)爭(zhēng)會(huì)越來(lái)越激烈,效率就越低。
對(duì)比圖:
- Hashtable
- JDK1.7 的 ConcurrentHashMap
- JDK1.8 的 ConcurrentHashMap(TreeBin: 紅黑二叉樹(shù)節(jié)點(diǎn);Node: 鏈表節(jié)點(diǎn))