蔚來測開一面:HashMap從1.7開始到1.8的過程,既然都解決不了并發安全問題,為什么還要進一步解決環形鏈表的問題?

文章目錄

    • 問題的根源:JDK 1.7 的設計缺陷
    • 為什么必須解決這個問題?
      • 1\. 故障等級完全不同 💣
      • 2\. JDK 1.8 的解決方案:一石二鳥 🦅
      • 3\. 為“不小心”的開發者提供一層保障 🛡?
    • 結論

這是一個非常好的問題,它直擊了技術演進的核心: 即使不能解決所有問題,也要優先解決最致命的問題

簡單來說,解決環形鏈表問題,并不是為了實現線程安全,而是為了消除一個在并發場景下會導致服務器CPU 100%直至宕機的“定時炸彈”

這是一個關于**故障嚴重性(Failure Severity)**的權衡問題。


問題的根源:JDK 1.7 的設計缺陷

在 JDK 1.7 中,HashMap 擴容(resize)時轉移數據的 transfer 方法使用了頭插法

  • 頭插法:在將舊數組的元素轉移到新數組時,新來的元素總被放在鏈表的頭部。
  • 問題所在:在單線程下,頭插法會使鏈表順序反轉,這沒問題。但在多線程并發擴容時,兩個線程可能同時操作同一個鏈表。一個線程執行一半被掛起,另一個線程完成了擴容導致鏈表反轉。當第一個線程恢復執行時,它會基于一個已經改變的鏈表繼續操作,這會導致鏈表節點的 next 指針互相指向,最終形成一個環形鏈表

這個環形鏈表一旦形成,后續對該位置的 get() 操作就會陷入無限循環,導致CPU占用率飆升到100%,整個應用或服務器都會被拖垮。


為什么必須解決這個問題?

現在回到你的核心問題:既然HashMap本來就不是線程安全的,并發使用時數據丟失、不一致等問題都可能發生,為什么還要專門修復環形鏈表這個bug?

1. 故障等級完全不同 💣

HashMap 在并發下可能遇到的問題可以分為兩類:

  • 數據不一致 (Data Inconsistency): 比如兩個線程同時 put,一個線程的數據覆蓋了另一個,導致數據丟失。這屬于數據問題,雖然也很糟糕,但通常不會讓整個應用程序崩潰。
  • 致命的系統崩潰 (Fatal System Crash): 環形鏈表導致的無限循環,會耗盡CPU資源,引起拒絕服務(DoS)。這是一個系統級的災難性故障。

打個比方:
數據不一致就像是兩個售票員賣了同一張電影票,會導致顧客(數據)沖突,需要業務邏輯去處理。
而環形鏈表就像是售票系統的后臺代碼進入了死循環,整個售票系統都癱瘓了,誰也買不了票。

顯然,消除一個能讓服務器宕機的Bug,其優先級遠高于處理一般的數據不一致問題

2. JDK 1.8 的解決方案:一石二鳥 🦅

JDK 1.8 對 HashMap 進行了重大重構,主要做了兩件事,順便解決了環形鏈表問題:

  • 引入紅黑樹 (Red-Black Tree): 這是1.8最大的性能優化。當鏈表長度超過一定閾值(默認為8)時,鏈表會轉化為紅黑樹,將該位置的查找時間復雜度從 O(n) 優化到 O(log n)。這是重構的主要動機之一。

  • 修改擴容算法為“尾插法”: 在數據轉移時,保持鏈表元素的原有順序,將元素依次插入到新鏈表的尾部。因為順序保持不變,就不會出現1.7中指針反轉交錯形成環路的情況。這個修改順手就根除了環形鏈表這個“定時炸彈”

所以,JDK 團隊在進行性能優化的同時,也修復了這個已知的、非常嚴重的設計缺陷。

3. 為“不小心”的開發者提供一層保障 🛡?

雖然官方文檔明確指出 HashMap 非線程安全,但現實中總有開發者會誤用或者在一些自認為安全的場景下不慎造成并發。

與其留著一個會導致服務器崩潰的“地雷”,不如讓它在被誤用時表現得“溫和”一些。JDK 1.8 之后,即使你在并發場景下誤用了 HashMap,最可能發生的是數據丟失,而不再是整個應用的崩潰。這是一種更“安全失敗”(Fail-Safe)的設計哲學。


結論

總而言之,從1.7到1.8的演進,解決環形鏈表問題并非為了讓 HashMap 變得線程安全,而是:

  1. 拆除了一個會導致系統崩潰的“核彈級”Bug。
  2. 作為性能優化(引入紅黑樹)過程中的一個必然修復。
  3. 降低了誤用HashMap時帶來的風險,使框架更健壯。

面試官問這個問題,就是想考察你是否理解技術決策背后的權衡和深層原因,而不僅僅是背誦“1.7是頭插法,1.8是尾插法和紅黑樹”。

正確的并發選擇:在需要保證線程安全的場景下,我們應該始終使用 ConcurrentHashMap

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88380.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88380.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88380.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AI技術正以前所未有的速度重塑職業生態與行業格局,尤其在自動化測試領域,AI驅動的測試框架通過智能化、低代碼化重構傳統測試流程。

AI技術正以前所未有的速度重塑職業生態與行業格局,尤其在自動化測試領域,AI驅動的測試框架通過智能化、低代碼化重構傳統測試流程。以下從職業影響、技術架構、行業應用及應對策略四個維度展開分析,結合代碼示例與框架設計圖解:一…

在 Mac 上安裝 Java 和 IntelliJ IDEA(完整筆記)

目錄 檢查是否已安裝 Java安裝 Java(JDK)設置 JAVA_HOME 環境變量安裝 IntelliJ IDEA配置 IntelliJ IDEA 使用 JDK驗證和測試環境是否成功 1. 檢查是否已安裝 Java 打開終端(Terminal),輸入: java -vers…

基于Java+Maven+Testng+Selenium+Log4j+Allure+Jenkins搭建一個WebUI自動化框架(2)對框架加入業務邏輯層

在上篇中,我們已經搭建好了框架的基本雛形,但只是引入了頁面層、用例層的思想,我們在實際使用中會發現,如果我們很多的用例需要很多前置工作,這些前置工作又有可能涉及到多個頁面,那么我們在維護的時候就會…

uniapp ruoyi-app 中使用checkbox 無法選中問題

<view class"flex align-center"> <checkbox-group> <label> <checkbox value"cb" checked"true" /> 記住密碼 </label> </checkbox-group> </view>colorui.css 文件中注釋掉兩處即可全局搜索…

如何快速學習GO語言

https://go.dev/tour/welcome/1 這個是官方的引導&#xff0c;很實用基本重點內容都涵蓋了&#xff0c;并且可以一邊學習一邊練習&#xff0c;非常好用 簡單介紹一下&#xff1a; Hello, 世界 歡迎訪問 Go 編程語言教程。 本教程分為幾個模塊&#xff0c;點擊本頁左上角的 …

AI 產品經理必看:神秘技術架構圖如何打通跨團隊溝通壁壘?

? 你好&#xff0c;我是 三橋君 引言 在AI產品的開發過程中&#xff0c;技術架構圖是連接業務需求與技術實現的橋梁。然而&#xff0c;許多AI產品經理常常面臨以下挑戰&#xff1a;研發團隊認為需求描述不清晰&#xff0c;業務團隊與技術團隊溝通不暢&#xff0c;技術選型時…

【科研繪圖系列】R語言繪制解剖圖

文章目錄 介紹加載R包數據下載導入數據數據預處理畫圖系統信息參考介紹 【科研繪圖系列】R語言繪制解剖圖 加載R包 # install.packages("devtools") # library(devtools) # devtools::install_github("jespermaag/gganatogram")library(gganatogram) li…

【unity編輯器開發與拓展EditorGUILayoyt和GUILayoyt】

EditorGUILayout 與 GUILayout 的核心區別及使用場景詳解 一、對比表特性GUILayoutEditorGUILayout命名空間UnityEngineUnityEditor使用場景運行時 UI 編輯器擴展僅限編輯器擴展控件風格基礎游戲風格&#xff08;無編輯器優化&#xff09;原生 Unity 編輯器風格布局復雜度基礎…

【數據結構】8. 二叉樹

文章目錄一、樹的概念及結構1、樹的概念2、樹的相關概念3、樹的表示4、樹的實際運用二、二叉樹的概念及結構1、二叉樹的概念2、特殊的二叉樹3、二叉樹的性質4、二叉樹的存儲結構三、二叉樹的順序結構及實現1、二叉樹的順序結構2、堆的概念及結構3、堆的實現0&#xff09;準備工…

Spring MVC中異常處理

1.全局異常處理1.1什么是全局異常處理器全局異常處理器是SpringMVC框架中的一種異常處理機制&#xff0c;用于統一處理由控制器拋出的異常。全局異常處理器可以幫助我們捕獲和處理控制器中的異常&#xff0c;并且根據不同的異常類型進行不同的處理操作&#xff0c;從而保障應用…

imx6ull-系統移植篇2—— U-Boot 命令使用(上)

目錄 前言 U-Boot 命令 help 信息查詢命令 bdinfo printenv version 環境變量操作命令 setenv 和 saveenv 修改環境變量 新建環境變量 刪除環境變量 內存操作命令 md nm mm mw cp cmp 網絡操作命令 ping 命令 dhcp 命令 nfs 命令 tftp 命令 EMMC 和 S…

vector之動態二維數組的底層

引言&#xff1a;在計算機編程領域&#xff0c;二維動態數組是一種能夠在程序運行期間動態調整其大小的二維數組數據結構。它與靜態二維數組的關鍵區別在于&#xff0c;靜態二維數組在編譯時就需要確定其大小&#xff0c;而二維動態數組的大小可以在程序運行過程中根據實際需求…

第十六天,7月10日,八股

1、mybatis的延遲加載需要時才加載關聯對象&#xff0c;而不是查詢主對象時&#xff0c;立刻加載所有關聯對象&#xff0c;這樣可以提高查詢性能并減少不必要的數據庫訪問&#xff0c;例如&#xff1a;一個訂單表包含著商品列表&#xff08;一對多&#xff09;&#xff0c;當查…

CSS中的Element語法

1.1 Element語法1.1.1 案例 1. 快速生成10個div,并且每個div里面是從1到10的內容2.生成一個div標簽&#xff0c;類名為one,并且同時生成一個id為first的p標簽1.1.2 快速生成CSS樣式語法 CSS基本采取簡寫形式即可 比如w22 按住tab鍵 可以生成 width:200px比如lh26px 按住tab鍵 可…

Go從入門到精通(21) - 一個簡單web項目-添加swagger文檔

Go從入門到精通(20)-一個簡單web項目-服務搭建 文章目錄Go從入門到精通(20)-一個簡單web項目-服務搭建前言前期準備為API 添加 Swagger 文檔1.安裝依賴2.添加 Swagger 注釋main.goapp.goapi.gopublic_handler.goauth_handler.gocommon_constant.gocommon_dto.gotoken_utils.go3…

自動駕駛環境感知:天氣數據采集與融合技術實戰

天氣與我們日常各類生活場景密不可分&#xff0c;在駕駛場景里當車主發動汽車準備駛向目的地時&#xff0c;窗外的陰晴或許只是直觀感受&#xff0c;而真正影響駕駛安全與行程效率的&#xff0c;可能是幾公里外的突發暴雨、橋面的結冰預警&#xff0c;或是前方路段的強側風等級…

基于svga+uniapp的微信小程序動畫組件開發指南

lottie動畫指南 效果 概述 本項目使用 svgaplayer.weapp.js 庫來實現 SVGA 動畫播放功能&#xff0c;支持在微信小程序、H5 等多端環境下播放高質量的矢量動畫。SVGA 是一種跨平臺的開源動畫格式&#xff0c;具有文件小、渲染性能高的特點。 技術棧 核心庫: svgaplayer.wea…

數據結構與算法——計算直線的交點數

前言&#xff1a; 這是之前做的一道筆試題&#xff0c;當時沒寫出來煩惱很久&#xff0c;這次記錄一下。 題目鏈接&#xff1a; Dotcpp--題目 1174: 計算直線的交點數 參考文章&#xff1a; CSDN--槐陽7--計算直線的交點數 題目&#xff1a; 解題思考&#xff1a; 在當時…

大模型及agent開發6 OpenAI Assistant API 高階應用 - 流式輸出功能

1.Assistant API 的主要優點&#xff1a; 減少編碼工作量、自動管理上下文窗口、安全的訪問控制、工具和文檔的輕松集成 本節講應用設計和性能流式輸出&#xff1a;借助流式輸出&#xff0c;可以讓應用程序實時處理和響應用戶輸入。具體來說&#xff0c;這種技術允許數據在生成…

React Native安卓劉海屏適配終極方案:僅需修改 AndroidManifest.xml!

&#x1f4cc; 問題背景在 React Native 開發中&#xff0c;我們經常會遇到安卓設備劉海屏&#xff08;Notch&#xff09;適配問題。即使正確使用了 react-native-safe-area-context 和 react-navigation&#xff0c;在一些安卓設備&#xff08;如小米、華為、OPPO 等&#xff…