HashMap中環(huán)及死循環(huán)形成原因分析

本文通過源碼分析并發(fā)情況下jdk1.7中HashMap形成的著名的死循環(huán)問題。

進(jìn)入分析模式以前了解下幾個必備知識點:

1.JVM內(nèi)存模型

本文只做必要的簡單介紹

主內(nèi)存、工作內(nèi)存、執(zhí)行引擎


圖片發(fā)自簡書App


2.put源碼邏輯流程


圖片發(fā)自簡書App


3.HashMap.Entry結(jié)構(gòu)


圖片發(fā)自簡書App



好了, 熟悉以上知識點后,可以開始按照假定的線程執(zhí)行步驟來重現(xiàn)環(huán)的形成和死循環(huán)的發(fā)生

1.初始化一個Map

final Map<String, Object> map = new HashMap<String, Object>(4);


2.線程安全的put三個對象

map.put("1","S");

map.put("7","A");

map.put("13","C");

此時在堆中已經(jīng)為HashMap分配一塊內(nèi)存,結(jié)構(gòu)如下


3.用多線程制造并發(fā)put

ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

for(int i = 0; i<1000;i++){

? ? ? ? executor.execute(new Thread(){

public void run(){

map.put(Math.random()*10+"", "hello world");

}

});

}

executor.shutdown();


4.假設(shè)此時并發(fā)線程thread1發(fā)起操作put("17","A");擴(kuò)容觸發(fā)執(zhí)行到途中綠框那一行,cpu分配的時間片用完,上下文切換,table保存到thread1工作內(nèi)存中


5.假設(shè)此時并發(fā)線程thread2發(fā)起操作put("27","Aa");觸發(fā)擴(kuò)容發(fā)生;繼續(xù)假設(shè)thread2有夠多的時間片;可以循環(huán)足夠次數(shù)將原始的hashMap中的元素全部轉(zhuǎn)移,以下藍(lán)框內(nèi)代碼循環(huán)三次

6.轉(zhuǎn)移第一次循環(huán)后


7.轉(zhuǎn)移第二次循環(huán)后;讓我們假設(shè)第二次循環(huán)在newTable上的哈希后下標(biāo)和第一個元素是在同一下標(biāo)(此二連續(xù)的位置分配在同一下標(biāo)是后面形成環(huán)的必要條件)


8.轉(zhuǎn)移第三次循環(huán)后;讓我們假設(shè)第三次循環(huán)在newTable上的哈希后下標(biāo)和第一,第二個元素不是同一下標(biāo)

9.擴(kuò)容完成thread2將工作空間了的的newTable賦值給table

并加入新對象后

10.這時thread2執(zhí)行完成,thread1分配的CPU執(zhí)行周期爭取到了執(zhí)行時間

假設(shè)執(zhí)行此代碼的系統(tǒng)優(yōu)化結(jié)果是store-load;store-store指令未重排序

11.thread1接著綠色框框內(nèi)的往下執(zhí)行

12.thread1循環(huán)執(zhí)行

13.thread1循環(huán)執(zhí)行;形成環(huán)

14.thread1執(zhí)行賦值

15.死循環(huán)的形成有兩種情況:

a.此時thread3來put元素落在下標(biāo)5上且造成再一次擴(kuò)容,則會陷入死循環(huán)

b.get元素的key下標(biāo)值也是5且不是這兩個元素中的任何一個, 則會陷入死循環(huán)

源碼如下:

總結(jié): 根本原因是HashMap中的table是共享且非線程安全的。

在觸發(fā)擴(kuò)容條件時,并發(fā)對HashMap的table進(jìn)行擴(kuò)容時會對table逆序轉(zhuǎn)移,有可能造成環(huán)的形成,形成環(huán)之后循環(huán)取元素時造成死循環(huán)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容