Java源碼解析ConcurrentHashMap的初始化
首先看一下代碼
private final Node<K,V>[] initTable() { Node<K,V>[] tab; int sc; while ((tab = table) == null || tab.length == 0) { // 第一次檢查 if ((sc = sizeCtl) < 0) Thread.yield(); // lost initialization race; just spin else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { try { if ((tab = table) == null || tab.length == 0) {// 第二次檢查 int n = (sc > 0) ? sc : DEFAULT_CAPACITY; @SuppressWarnings("unchecked") Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; table = tab = nt; sc = n - (n >>> 2); } } finally { sizeCtl = sc; } break; } } return tab; }
ConcurrentHashMap在初始化時(shí),如何進(jìn)行多線程間的同步?
ConcurrentHashMap
在初始化時(shí),首先會(huì)判斷,哈希表是否已經(jīng)初始化了。如果沒有,則嘗試進(jìn)行初始化。
首先會(huì)判斷sizeCtl
的值。sizeCtl是用于多線程之間同步的一個(gè)互斥變量。當(dāng)sizeCtl < 0時(shí),表示已經(jīng)有線程正在初始化哈希表或哈希表正在擴(kuò)容,此時(shí),不能再進(jìn)行操作。
此處sizeCtl其實(shí)是實(shí)現(xiàn)了自旋鎖的功能。自旋鎖,即,獲取鎖失敗時(shí),讓出CPU,稍后再進(jìn)行嘗試,重復(fù)這個(gè)過程,直到獲得到鎖為止。讓出CPU的動(dòng)作,是通過java中的Thread.yield()
來實(shí)現(xiàn)的。在學(xué)校學(xué)習(xí)java的時(shí)候曾經(jīng)接觸過線程的這個(gè)方法,但當(dāng)時(shí)不明白什么場景下會(huì)用到。原來,Thread.yield()方法可以用來實(shí)現(xiàn)自旋鎖。
這里,可以提出一個(gè)問題,自選鎖方式和死循環(huán)方式來判斷sizeCtl的值,有什么不同?
當(dāng)然是效率的不同。死循環(huán)時(shí),程序會(huì)頻繁讀取sizeCtl的值,在滿足條件之前,會(huì)浪費(fèi)很多CPU周期。而自選鎖的效率更高,因?yàn)楫?dāng)它判斷sizeCtl不滿足條件時(shí),會(huì)主動(dòng)讓出CPU,此時(shí),當(dāng)前線程會(huì)處于ready狀態(tài),等待下一次被處理器選中并執(zhí)行的機(jī)會(huì)。在這段時(shí)間里,其他的線程得以利用CPU周期。所以,自旋鎖的效率更高。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
- Java中遍歷ConcurrentHashMap的四種方式詳解
- java 使用ConcurrentHashMap和計(jì)數(shù)器實(shí)現(xiàn)鎖
- Java ConcurrentHashMap的使用示例
- java中ConcurrentHashMap的讀操作為什么不需要加鎖
- java基于ConcurrentHashMap設(shè)計(jì)細(xì)粒度實(shí)現(xiàn)代碼
- 基于Java并發(fā)容器ConcurrentHashMap#put方法解析
- java ConcurrentHashMap鎖分段技術(shù)及原理詳解
- Java concurrency集合之ConcurrentHashMap_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- Java集合ConcurrentHashMap詳解
相關(guān)文章
SpringCloud Finchley+Spring Boot 2.0 集成Consul的方法示例(1.2版本)
這篇文章主要介紹了SpringCloud Finchley+Spring Boot 2.0 集成Consul的方法示例(1.2版本),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08解決java連接虛擬機(jī)Hbase無反應(yīng)的問題
這篇文章主要介紹了解決java連接虛擬機(jī)Hbase無反應(yīng)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06java 輸入一個(gè)數(shù)字,反轉(zhuǎn)輸出這個(gè)數(shù)字的值(實(shí)現(xiàn)方法)
下面小編就為大家?guī)硪黄猨ava 輸入一個(gè)數(shù)字,反轉(zhuǎn)輸出這個(gè)數(shù)字的值(實(shí)現(xiàn)方法)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-10-10Python連接Java Socket服務(wù)端的實(shí)現(xiàn)方法
這篇文章主要介紹了Python連接Java Socket服務(wù)端的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01SpringBoot中的異常處理與參數(shù)校驗(yàn)的方法實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot中的異常處理與參數(shù)校驗(yàn)的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04