精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

為什么HashMap會產生死循環呢?

CodeSheep ? 來源:Java面試真題解析 ? 2023-12-21 09:06 ? 次閱讀

HashMap 死循環是一個比較常見、比較經典的問題,在日常的面試中出現的頻率比較高,今天這篇文章咱們就通過圖解的方式,帶大家徹底梳理和理解一下這個問題

前置知識

首先我們要了解一下為什么會有這個問題的發生?

死循環問題發生在 JDK 1.7 版本中,造成這個問題主要是由于 HashMap 自身的運行機制,加上并發操作,從而導致了死循環。在 JDK 1.7 中 HashMap 的底層數據實現是數組 + 鏈表的方式,如下圖所示:efb8482e-9f9c-11ee-8b88-92fbcf53809c.png

而 HashMap 在數據添加時使用的是頭插入,如下圖所示:

efbc58b0-9f9c-11ee-8b88-92fbcf53809c.png

HashMap 正常情況下的擴容實現如下圖所示:

efc7a058-9f9c-11ee-8b88-92fbcf53809c.png

舊 HashMap 的節點會依次轉移到新 HashMap 中,舊 HashMap 轉移的順序是 A、B、C,而新 HashMap 使用的是頭插法,所以最終在新 HashMap 中的順序是 C、B、A,也就是上圖展示的那樣。有了這些前置知識之后,咱們來看死循環是如何誕生的?

死循環執行步驟1

死循環是因為并發 HashMap 擴容導致的,并發擴容的第一步,線程 T1 和線程 T2 要對 HashMap 進行擴容操作,此時 T1 和 T2 指向的是鏈表的頭結點元素 A,而 T1 和 T2 的下一個節點,也就是 T1.next 和 T2.next 指向的是 B 節點,如下圖所示:

efd4244a-9f9c-11ee-8b88-92fbcf53809c.png

死循環執行步驟2

死循環的第二步操作是,線程 T2 時間片用完進入休眠狀態,而線程 T1 開始執行擴容操作,一直到線程 T1 擴容完成后,線程 T2 才被喚醒,擴容之后的場景如下圖所示:

efe63bd0-9f9c-11ee-8b88-92fbcf53809c.png

從上圖可知線程 T1 執行之后,因為是頭插法,所以 HashMap 的順序已經發生了改變,但線程 T2 對于發生的一切是不可知的,所以它的指向元素依然沒變,如上圖展示的那樣,T2 指向的是 A 元素,T2.next 指向的節點是 B 元素。

死循環執行步驟3

當線程 T1 執行完,而線程 T2 恢復執行時,死循環就建立了,如下圖所示:

eff47b82-9f9c-11ee-8b88-92fbcf53809c.png

因為 T1 執行完擴容之后 B 節點的下一個節點是 A,而 T2 線程指向的首節點是 A,第二個節點是 B,這個順序剛好和 T1 擴完容完之后的節點順序是相反的。

T1 執行完之后的順序是 B 到 A,而 T2 的順序是 A 到 B,這樣 A 節點和 B 節點就形成死循環了,這就是 HashMap 死循環導致的原因。

解決方案

HashMap 死循環的常用解決方案有以下 3 個:

使用線程安全容器 ConcurrentHashMap 替代(推薦使用此方案)。

使用線程安全容器 Hashtable 替代(性能低,不建議使用)。

使用 synchronized 或 Lock 加鎖 HashMap 之后,再進行操作,相當于多線程排隊執行(比較麻煩,也不建議使用)。

總結

HashMap 死循環發生在 JDK 1.7 版本中,形成死循環的原因是 HashMap 在 JDK 1.7 使用的是頭插法,頭插法 + 鏈表 + 多線程并發 + HashMap 擴容,這幾個點加在一起就形成了 HashMap 的死循環,解決死鎖可以采用線程安全容器 ConcurrentHashMap 替代。







審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 多線程
    +關注

    關注

    0

    文章

    275

    瀏覽量

    19850
  • JDK
    JDK
    +關注

    關注

    0

    文章

    80

    瀏覽量

    16548
  • hashmap
    +關注

    關注

    0

    文章

    14

    瀏覽量

    2263

原文標題:阿里二面:為什么HashMap會產生死循環

文章出處:【微信號:CodeSheep,微信公眾號:CodeSheep】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    關于死循環語句

    do{..........} while(1) 和for(;;)[..............]這兩個語句都代表死循環吧都是一樣的意思吧!
    發表于 09-26 17:37

    為什么STM32仿真調試時會進入SystemInit死循環

    為什么STM32仿真調試時會進入SystemInit死循環?怎樣去解決這個問題
    發表于 11-10 07:20

    外部中斷函數初始化,執行的時候進入死循環是為什么?

    外部中斷函數初始化,執行的時候進入死循環是為什么?
    發表于 11-25 08:10

    你怎么樣用C語言編寫死循環

    嵌入式系統中經常要用到無限循環,你怎么樣用C編寫死循環?  一、while(1) { }沒有劃定初始化、更新區域的代碼塊(位置)。這兩項代碼的書寫,就由作者來隨意設置(完成)。后人接手程序,就要
    發表于 12-15 07:20

    死鎖是什么?產生死鎖的主要原因有哪些

    鎖,就會造成系統死鎖。產生死鎖的三大主要原因:①系統資源不足②進程運行推進的順序不合適③資源分配不當死鎖的產生四個必要條件:①互斥條件:進程對所分配到的資源不允許其他進程訪問,若其他進程訪問該資源,只能等待,直至占有該資源的進程使用完成后釋放該資源。②環路等待條件(
    發表于 12-22 07:34

    如何去處理嵌入式軟件產生死鎖的情況

    嵌入式軟件產生死鎖的必要條件及原因有哪些?如何去處理嵌入式軟件產生死鎖的情況
    發表于 12-24 06:12

    怎么樣用C語言去編寫嵌入式系統中的死循環

    怎么樣用C語言去編寫嵌入式系統中的死循環?關鍵字volatile有什么含義嗎?
    發表于 12-24 07:46

    RT-Thread如何去發現該線程已經進入異常的死循環

    各位大佬,假在某個線程的執行代碼的異常執行流中,如else處理中寫了while(1)這種死循環代碼,rt-thread如何去發現該線程已經進入異常的死循環?求指教。
    發表于 10-18 09:57

    關于Java HashMap的認知

    HashMap詳解 HashMap 和 HashSet 是 Java Collection Framework 的兩個重要成員,其中 HashMap 是 Map 接口的常用實現類,HashSet
    發表于 09-27 16:34 ?0次下載
    關于Java <b class='flag-5'>HashMap</b>的認知

    為什么單片機的程序必須是死循環

    為何單片機的程序必須是死循環?!!這個問題困擾了我好久,然而答案卻是這個樣子的!單片機沒有操作系統,不像電腦有Windows,程序運行與結束有操作系統管理。單片機的程序是不能結束的,否則會使單片機系統出現不確定的狀態;一般編譯自己加上
    發表于 07-05 17:41 ?0次下載
    為什么單片機的程序必須是<b class='flag-5'>死循環</b>

    為什么單片機的主程序是死循環

    任何一個可用程序都必然是死循環程序,這不僅僅是指單片機程序。因為任何微處理器系統一旦開機,系統都在處理內部事件和外設響應,這個過程是一個循環過程,除非關機才能結束這個死循環程序。因此,對于單片機編程必須注意以下幾點
    發表于 07-15 17:38 ?5166次閱讀

    單片機的死循環有什么作用

    單片機是可編程器件,在使用時需要編寫滿足需求的程序。其C語言程序在各個端口、配置初始化完成后,進入一個死循環,一般用while(1){;}的形式。初始化完成后,單片機就在死循環內一遍又一遍的執行程序邏輯。復位后,就從頭開始,初
    發表于 08-09 17:01 ?5568次閱讀
    單片機的<b class='flag-5'>死循環</b>有什么作用

    如何避免Xil_Assert系列宏導致的死循環的情況

    在調試模式下,Xil_Assert系列宏會調用Xil_Assert來檢查參數是否正常。如果不正常,缺省情況下,沒有打印,進入死循環。 通過調用void Xil_AssertSetCallback
    的頭像 發表于 12-02 16:20 ?4033次閱讀
    如何避免Xil_Assert系列宏導致的<b class='flag-5'>死循環</b>的情況

    Too many open files錯誤導致服務器死循環

    在服務器編程中,經常會遇到 Too many open files 這個報錯,而且這個報錯如果處理不好,很有可能導致服務器死循環
    的頭像 發表于 05-23 09:08 ?1738次閱讀
    Too many open files錯誤導致服務器<b class='flag-5'>死循環</b>

    聊聊MCU死循環,用for(;;)還是while(1)?

    首先,問大家一個問題:你們寫單片機程序【死循環】時,喜歡用for(;;)還是while(1)?快來為你喜歡用的【死循環】打call,評論區等你哦~一位工程師發現,國外工程師在給demo在做死循環時用
    的頭像 發表于 04-29 08:10 ?804次閱讀
    聊聊MCU<b class='flag-5'>死循環</b>,用for(;;)還是while(1)?