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