Q:ConcurrentHashMap和HashMap的區(qū)別是什么?
A:
1.ConcurrentHashMap是線程安全的,HashMap是線程不安全的
2.ConcurrentHashMap不允許Key為null的值插入。而HashMap是可以的
Q:JDK8的ConcurrentHashMap和JDK7的ConcurrentHashMap有什么區(qū)別?
A:
1.JDK7的ConcurrentHashMap采用分段鎖的策略,將整個(gè)數(shù)組分成多個(gè)segment,對(duì)這些segment進(jìn)行分段加鎖,使用的鎖是ReentrantLock。而JDK8中的ConcurrentHashMap不采用分段鎖的方式,直接使用Synchronized來(lái)進(jìn)行。
2.JDK8中的ConcurrentHashMap新增了紅黑樹(shù),并且插入用的是尾插法。
3.JDK7中的ConcurrentHashMap進(jìn)行擴(kuò)容時(shí),是對(duì)當(dāng)前的segment進(jìn)行擴(kuò)容,不會(huì)對(duì)其他segment有影響。而JDK8中就跟HashMap一樣。整體擴(kuò)容,但是保證線程安全
Q:JDK7中的ConcurrentHashMap是如何擴(kuò)容的
A:JDK7中對(duì)每一段segment進(jìn)行擴(kuò)容,每一段segment的擴(kuò)容跟HashMap保持一致
Q:JDK8中的ConcurrentHashMap是如何擴(kuò)容的
A:在擴(kuò)容時(shí),首先會(huì)生成一個(gè)雙倍大小的數(shù)組,生成完數(shù)組后,線程就會(huì)開(kāi)始轉(zhuǎn)移元素,在擴(kuò)容的過(guò)程中,如果有其他線程在put,那么這個(gè)put線程會(huì)幫助去進(jìn)行元素的轉(zhuǎn)移,雖然叫轉(zhuǎn)移,但是其實(shí)是基于原數(shù)組上的Node信息去生成一個(gè)新的Node的,也就是原數(shù)組上的Node不會(huì)消失,因?yàn)樵跀U(kuò)容的過(guò)程中,如果有其他線程在get也是可以的。
Q:ConcurrentHashMap是如何保證線程安全的
A:
1.在JDK7的時(shí)候。ConcurrentHashMap是通過(guò)ReentrantLock+CAS+分段思想來(lái)保證的并發(fā)安全的,在JDK7的ConcurrentHashMap中,首先有一個(gè)Segment數(shù)組,存的是Segment對(duì)象,Segment相當(dāng)于一個(gè)小HashMap,Segment內(nèi)部有一個(gè)HashEntry的數(shù)組,也有擴(kuò)容的閾值,同時(shí)Segment繼承了ReentrantLock類,同時(shí)在Segment中還提供了put,get等方法,比如Segment的put方法在一開(kāi)始就會(huì)去加鎖,加到鎖之后才會(huì)把key,value存到Segment中去,然后釋放鎖。同時(shí)在ConcurrentHashMap的put方法中,會(huì)通過(guò)CAS的方式把一個(gè)Segment對(duì)象存到Segment數(shù)組的某個(gè)位置中。同時(shí)因?yàn)橐粋€(gè)Segment內(nèi)部存在一個(gè)HashEntry數(shù)組,所以和HashMap對(duì)比來(lái)看,相當(dāng)于分段了,每段里面是一個(gè)小的HashMap,每段公用一把鎖,同時(shí)在ConcurrentHashMap的構(gòu)造方法中是可以設(shè)置分段的數(shù)量的,叫做并發(fā)級(jí)別concurrencyLevel.
2.在JDK8的時(shí)候,ConcurrentHashMap是通過(guò)synchronized+cas來(lái)實(shí)現(xiàn)了。在JDK8中只有一個(gè)數(shù)組,就是Node數(shù)組,Node就是key,value,hashcode封裝出來(lái)的對(duì)象,和HashMap中的Entry一樣,在JDK8中通過(guò)對(duì)Node數(shù)組的某個(gè)index位置的元素進(jìn)行同步,達(dá)到該index位置的并發(fā)安全。同時(shí)內(nèi)部也利用了CAS對(duì)數(shù)組的某個(gè)位置進(jìn)行并發(fā)安全的賦值。