成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

ConcurrentHashMap探究

zombieda / 3277人閱讀

摘要:是線程安全,性能出色的的線程安全實(shí)現(xiàn),相比較他是線程安全的,相比較他的性能優(yōu)勢(shì)非常明顯。的源碼其實(shí)很簡(jiǎn)單,和的結(jié)構(gòu)一致,但是每一個(gè)方法都是用來(lái)修飾,以保證操作是線程安全的。這樣在多線程的情況下,只有一個(gè)線程獲取鎖操作中的數(shù)據(jù)。

ConcurrentHashMap

ConcurrentHashMap是線程安全,性能出色的Map的線程安全實(shí)現(xiàn),相比較HashMap他是線程安全的,相比較HashTable他的性能優(yōu)勢(shì)非常明顯。他的使用很簡(jiǎn)單,這里主要是想要探究一下ConcurrentHashMap的實(shí)現(xiàn)原理。
在這里一共有 個(gè)問(wèn)題需要搞明白。

ConcurrentHashMap為什么比HashTable的性能要高?

ConcurrentHashMap在JDK8和JDK7有什么變化,為什么會(huì)有這種變化,對(duì)我們開(kāi)發(fā)有什么啟示?

為什么在JDK8中使用Synchronized而不是用ReentrantLock來(lái)實(shí)現(xiàn)加鎖?

帶著這幾個(gè)問(wèn)題我們來(lái)分析一下ConcurrentHashMap的源碼吧。

ConcurrentHashMap定義

在JDK8(JDK7也是一樣)中ConcurrentHashMap的定義如下:

public class ConcurrentHashMap extends AbstractMap
    implements ConcurrentMap, Serializable {
ConcurrentHashMap在JDK7中的實(shí)現(xiàn)

Java7中ConcurrentHashMap的實(shí)現(xiàn)是基于分段鎖實(shí)現(xiàn)的。他的底層數(shù)據(jù)結(jié)構(gòu)仍然是數(shù)組+鏈表,與HashTable不同的是,ConcurrentHashMap的最外層不是一個(gè)大的數(shù)組,而是一個(gè)Segment數(shù)組(分段鎖的實(shí)現(xiàn))。分段鎖減小了鎖的粒度,提高了并發(fā)程度。這也是為什么比HashTable效率要高的原因。
HashTable的源碼其實(shí)很簡(jiǎn)單,HashTable和HashMap的結(jié)構(gòu)一致,但是每一個(gè)方法都是用Synchronized來(lái)修飾,以保證操作是線程安全的。這樣在多線程的情況下,只有一個(gè)線程獲取鎖操作hashTable中的數(shù)據(jù)。而CourrentHashMap則不是,它允許最多有segment數(shù)組長(zhǎng)度個(gè)線程同時(shí)操作ConcurrentHashMap中的數(shù)據(jù)。

ConcurrentHashMap的整體結(jié)構(gòu)如下(圖片來(lái)源:http://www.jasongj.com/java/c...):

ConcurrentHashMap的定義:

public class ConcurrentHashMap extends AbstractMap
        implements ConcurrentMap, Serializable {
    private static final long serialVersionUID = 7249069246763182397L;

    /**
     * 表的默認(rèn)容量
     */
    static final int DEFAULT_INITIAL_CAPACITY = 16;

    /**
     * 默認(rèn)擴(kuò)容因子
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * segments數(shù)組的默認(rèn)長(zhǎng)度,為了能通過(guò)按位與的散列算法來(lái)定位segments數(shù)組的索引,必須保證segments數(shù)組的長(zhǎng)度是2的N次方
     */
    static final int DEFAULT_CONCURRENCY_LEVEL = 16;

    /**
     * HashEntry最大容量
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * segment的最小容量
     */
    static final int MIN_SEGMENT_TABLE_CAPACITY = 2;

    /**
     * segment的最大容量
     */
    static final int MAX_SEGMENTS = 1 << 16; // slightly conservative

    /**
     * 重試次數(shù),無(wú)鎖的情況下嘗試兩次
     */
    static final int RETRIES_BEFORE_LOCK = 2;

    /**
     * 散列運(yùn)算的掩碼,等于ssize-1
     */
    final int segmentMask;

    /**
     * 定位參與散列運(yùn)算的位數(shù),等于32-sshift
     */
    final int segmentShift;

    /**
     * 定義segment數(shù)組
     */
    final Segment[] segments;

Segment定義:

static final class Segment extends ReentrantLock implements Serializable {
    transient volatile HashEntry[] table;
    transient int count;
    transient int modCount;
    //擴(kuò)容量,默認(rèn)為表的容量*加載因子,實(shí)際量超過(guò)這個(gè)值的時(shí)候,進(jìn)行擴(kuò)容
    transient int threshold;
    //segment中hashEntry的擴(kuò)容因子
    final float loadFactor;

}

get()操作經(jīng)過(guò)兩次散列找到HashEntry,然后進(jìn)行遍歷的操作,get方法使用的變量都是volatile類型的,可以保證線程可見(jiàn),能夠被多線程同時(shí)讀,并且保證不會(huì)讀取到過(guò)期的值,在get操作中需要讀count和value兩個(gè)共享變量,所以不需要加鎖,volatile字段的寫(xiě)入操作會(huì)先于讀操作,所有即使有一個(gè)線程在修改,get也能獲取到最新的值。

put() 先對(duì)變量的hashCode進(jìn)行一次再散列然后定位到Segment,然后再Segment中進(jìn)行插入操作。如果HashEntry數(shù)組超過(guò)threshold,那么擴(kuò)容,擴(kuò)容只是針對(duì)Segment進(jìn)行擴(kuò)容。

size() 統(tǒng)計(jì)ConcurrentHashMap中元素的個(gè)數(shù),需要對(duì)Segment中所有元素進(jìn)行求和,Segment里全局變量count是一個(gè)volatile類型的變量,累加可以獲取元素的總個(gè)數(shù),但是不一定準(zhǔn)確,因?yàn)槭褂眠^(guò)的count再后面可以改變,最后的方法就是阻塞put,remove,clean等元素操作的方法,但是這樣非常低效。所以Concurrenthashmap通過(guò)嘗試兩次不鎖來(lái)統(tǒng)計(jì)segment的元素大小,如果兩次結(jié)果不一樣,那么使用加鎖的方式來(lái)統(tǒng)計(jì),容器是否變化是通過(guò)modCount是否變化來(lái)確定的。

ConcurrentHashMap在JDK8中的實(shí)現(xiàn)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77795.html

相關(guān)文章

  • java中ConcurrentHashMap的使用及在Java 8中的沖突方案

    摘要:中的使用及在中的沖突方案引言簡(jiǎn)稱是在作為的替代選擇新引入的,是包的重要成員。為了解決在頻繁沖突時(shí)性能降低的問(wèn)題,中使用平衡樹(shù)來(lái)替代鏈表存儲(chǔ)沖突的元素。目前,只有和會(huì)在頻繁沖突的情況下使用平衡樹(shù)。 java中ConcurrentHashMap的使用及在Java 8中的沖突方案 1、引言 ConcurrentHashMap(簡(jiǎn)稱CHM)是在Java 1.5作為Hashtable的替代選擇新...

    kun_jian 評(píng)論0 收藏0
  • 高并發(fā) - 收藏集 - 掘金

    摘要:在中一般來(lái)說(shuō)通過(guò)來(lái)創(chuàng)建所需要的線程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來(lái)研究學(xué)習(xí)一下AbstractQueuedSynchronizer類的相關(guān)原理,java.util.concurrent包中很多類都依賴于這個(gè)類所提供的隊(duì)列式...

    levius 評(píng)論0 收藏0
  • 高并發(fā) - 收藏集 - 掘金

    摘要:在中一般來(lái)說(shuō)通過(guò)來(lái)創(chuàng)建所需要的線程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來(lái)研究學(xué)習(xí)一下AbstractQueuedSynchronizer類的相關(guān)原理,java.util.concurrent包中很多類都依賴于這個(gè)類所提供的隊(duì)列式...

    fantix 評(píng)論0 收藏0
  • 高并發(fā)

    摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢?jiàn)它的使用,在開(kāi)始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購(gòu),是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽(tīng)名字多牛逼,來(lái),我們一步一步來(lái)?yè)羝魄皟蓚€(gè)名詞,今天我們首先來(lái)說(shuō)說(shuō)分布式。 探究...

    supernavy 評(píng)論0 收藏0
  • 高并發(fā)

    摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢?jiàn)它的使用,在開(kāi)始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購(gòu),是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽(tīng)名字多牛逼,來(lái),我們一步一步來(lái)?yè)羝魄皟蓚€(gè)名詞,今天我們首先來(lái)說(shuō)說(shuō)分布式。 探究...

    ddongjian0000 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<