HashMap 在多線程環境下可能引發哪些問題?如何解決?


HashMap 在多線程環境下可能引發哪些問題?

答案:
在多線程同時操作 HashMap 時,可能引發 死循環數據丟失臟數據讀取 等問題。
根本原因:
HashMap 的設計是非線程安全的,多線程并發修改其結構(如擴容、插入、刪除)會導致內部鏈表或紅黑樹結構損壞。


具體問題分析:

1. 死循環(JDK 1.7 及之前版本的經典問題)
  • 觸發場景: 多個線程同時觸發擴容(resize)。
  • 原因:
    JDK 1.7 的擴容采用“頭插法”遷移鏈表,多線程并發操作可能導致鏈表形成環狀結構(循環鏈表)。
    舉例:
    想象兩個搬運工(線程)同時把書從一個舊書架搬到新書架,但搬運時不小心把書的順序弄反了,結果某些書被循環引用,再也找不到正確的順序了。
2. 數據丟失
  • 觸發場景: 多個線程同時插入新數據。
  • 原因:
    兩個線程同時計算哈希并定位到同一個桶(數組位置),后插入的線程可能覆蓋前一個線程寫入的值。
    舉例:
    兩個人(線程)同時往同一個抽屜里放文件,后放的人直接把自己的文件蓋在別人的文件上,導致別人的文件丟失。
3. 臟數據讀取
  • 觸發場景: 一個線程正在擴容,另一個線程嘗試讀取數據。
  • 原因:
    擴容過程中鏈表可能被臨時拆分成兩部分,此時讀取的數據可能不完整或為舊數據。
    類比:
    搬家時(擴容),你一邊搬箱子一邊查字典(讀數據),可能查到的詞條是已經搬走的舊箱子里的內容。

如何解決?

方案 1:使用線程安全的替代類
  • 推薦方法: ConcurrentHashMap
    原理:

    • JDK 1.7 采用分段鎖(每個段獨立加鎖,提高并發度)。
    • JDK 1.8 改為基于 CASsynchronized 鎖單個桶(更細粒度)。
      舉例:
      把倉庫分成多個小房間(分段),每個房間有獨立的鎖,搬運工可以同時操作不同房間,互不干擾。
  • 其他方法(不推薦):

    • Hashtable:全表鎖,性能差(類似整個倉庫只有一把鎖,所有人排隊操作)。
    • Collections.synchronizedMap(new HashMap()):包裝類,同樣全表鎖。
方案 2:手動加鎖(僅限特殊場景)
  • 方法: 使用 synchronizedReentrantLock 包裹所有 HashMap 操作。
    缺點: 完全串行化,性能極低,不如直接使用 ConcurrentHashMap

舉個栗子 🌰

問題復現(死循環):

// JDK 1.7 環境下運行以下代碼
HashMap<Integer, Integer> map = new HashMap<>(2); // 容量2,閾值1.5
// 線程1和線程2同時執行 put 操作觸發擴容
map.put(5, 5);  // 哈希沖突可能導致鏈表成環

此時調用 map.get(5) 可能陷入死循環(CPU 100%)。

解決方案:
直接替換為 ConcurrentHashMap

ConcurrentHashMap<Integer, Integer> safeMap = new ConcurrentHashMap<>();
// 多線程操作安全

總結

問題觸發場景解決方案
死循環多線程并發擴容(JDK1.7)使用 ConcurrentHashMap
數據丟失多線程同時插入同一位置使用線程安全的容器
臟數據讀取擴容與讀操作并發避免并發讀寫非線程安全容器

關鍵點:

  • JDK 1.8 的 HashMap 仍非線程安全(尾插法解決死循環,但其他問題仍存在)。
  • 永遠不要在多線程中直接使用 HashMap,優先選擇 ConcurrentHashMap

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

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

相關文章

告別GitHub連不上!一分鐘快速訪問方案

一、當GitHub抽風時&#xff0c;你是否也這樣崩潰過&#xff1f; &#x1f621; npm install卡在node-sass半小時不動&#x1f62d; git clone到90%突然fatal: early EOF&#x1f92c; 改了半天hosts文件&#xff0c;第二天又失效了... 根本原因&#xff1a;傳統代理需要復雜…

【軟考-架構】2.1、操作系統概述-進程管理-同步互斥

?資料&文章更新? GitHub地址&#xff1a;https://github.com/tyronczt/system_architect 文章目錄 操作系統知識操作系統概述進程組成和狀態&#x1f4af;考試真題前趨圖進程資源圖&#x1f4af;考試真題問題1問題2 ?【重點】進程同步與互斥?&#x1f4af;考試真題問題…

基于開源庫編寫MQTT通訊

目錄 1. MQTT是什么&#xff1f;2. 開發交互UI3. 服務器核心代碼4. 客戶端核心代碼5. 消息訂閱與發布6. 通訊測試7. MQTT與PLC通訊最后. 核心總結 1. MQTT是什么&#xff1f; MQTT&#xff08;Message Queuing Terlemetry Transport&#xff09;消息隊列遙測協議&#xff1b;是…

在VScode下配置C/C++環境(tasks.json、launch.json、c_cpp_properties.json)

文章目錄 1. tasks.json、launch.json配置文件中參數(屬性)的說明2. tasks.json介紹3. launch.json介紹4. 直接生成tasks.json、launch.json配置文件的另外一種方式5. c_cpp_properties.json介紹6. 運行多個C/C文件7. 命令行方式編譯C 1. tasks.json、launch.json配置文件中參數…

ORB-SLAM2源碼學習(六):相機跟蹤(局部地圖跟蹤和關鍵幀創建)

目錄 1.局部地圖跟蹤 1.1 更新局部關鍵幀UpdateLocalKeyFrames 1.2 更新局部地圖點&#xff08;來自局部關鍵幀&#xff09;UpdateLocalPoints() 1.3 投影匹配 2. 對比四種跟蹤方式以及使用的投影匹配 3.關鍵幀創建 3.1 判斷是否需要創建新關鍵幀: NeedNewKeyFrame() 3…

PostgreSQL時間計算大全:從時間差到時區轉換(保姆級教程)

一、時間計算的三大核心場景 當你遇到這些需求時&#xff0c;本文就是你的救星&#x1f31f;&#xff1a; 倒計時功能&#xff1a;計算活動剩余天數 用戶行為分析&#xff1a;統計操作間隔時間 跨國系統&#xff1a;多時區時間統一管理 報表生成&#xff1a;自動計算同比/環…

Qt6.8.2創建WebAssmebly項目使用FFmpeg資源

Qt6新出了WebAssmebly功能&#xff0c;可以將C寫的軟件到瀏覽器中運行&#xff0c;最近一段時間正在研究這方便內容&#xff0c;普通的控件響應都能實現&#xff0c;今天主要為大家分享如何將FFmpeg中的功能應用到瀏覽器中。 開發環境&#xff1a;window11&#xff0c;Qt6.8.2…

DeepSeek V3 源碼:從入門到放棄!

從入門到放棄 花了幾天時間&#xff0c;看懂了DeepSeek V3 源碼的邏輯。源碼的邏輯是不難的&#xff0c;但為什么模型結構需要這樣設計&#xff0c;為什么參數需要這樣設置呢&#xff1f;知其然&#xff0c;但不知其所以然。除了模型結構以外&#xff0c;模型的訓練數據、訓練…

【leetcode hot 100 240】搜索二維矩陣Ⅱ

解法一&#xff1a;直接查找 class Solution {public boolean searchMatrix(int[][] matrix, int target) {for(int i0; i<matrix.length; i){for(int j0; j<matrix[0].length; j){if(matrix[i][j]>target){break;}if(matrix[i][j]target){return true;}}}return fal…

UE4 組件 (對話組件)

制作一個可以生成對話氣泡&#xff0c;顯示對話臺詞的簡單組件。這個組件要的變量&#xff1a;臺詞&#xff08;外部傳入&#xff09;。功能&#xff1a;開始對話&#xff08;生成氣泡UI&#xff09; &#xff0c;結束對話。 一、對話組件創建 二、開始對話事件 1、注意這里獲…

自動化同步多服務器數據庫表結構

當項目每次進行版本升級的時候&#xff0c;如果在這次迭代中涉及表結構變更&#xff0c;需要將不同的生產環境下&#xff0c;都需要同步表結構的DDL語句&#xff0c;比較麻煩&#xff0c;而且還有可能忘記同步腳本&#xff0c;導致生產環境報錯.... 該方案采用SpringBootMybat…

DeepSeek安全:AI網絡安全評估與防護策略

&#x1f345; 點擊文末小卡片 &#xff0c;免費獲取網絡安全全套資料&#xff0c;資料在手&#xff0c;漲薪更快 本文基于現有的公開資料&#xff0c;從企業資深網絡安全專家的視角&#xff0c;系統梳理DeepSeek技術在網絡安全領域的潛在貢獻與核心風險&#xff0c;并結合中國…

【論文筆記】Attentive Eraser

標題&#xff1a;Attentive Eraser: Unleashing Diffusion Model’s Object Removal Potential via Self-Attention Redirection Guidance Source&#xff1a;https://arxiv.org/pdf/2412.12974 收錄&#xff1a;AAAI 25 作者單位&#xff1a;浙工商&#xff0c;字節&#…

【powerjob】 powerjobserver注冊服務IP錯誤

1、問題&#xff1a;powerjobserver 4.3.6 的服務器上有多個網卡對應多個ip,示例 eth0 :IP1 &#xff0c;docker0:IP2 和worker 進行通信時 正確的應該時IP1 但是注冊顯示獲取的確實IP2,導致 worker 通過ip2和server通信&#xff0c;網絡不通&#xff0c;注冊不上 2、解決方案 …

視頻錄像機視頻通道是指什么

視頻錄像機的視頻通道是指攝像機在監控矩陣或硬盤錄像機設備上的視頻輸入的物理位置。 與攝像頭數量關系&#xff1a;在視頻監控系統中&#xff0c;有多少個攝像頭就需要多少路視頻通道&#xff0c;通道數量決定了視頻錄像機可接入攝像頭的數量&#xff0c;一般硬盤錄像機有4路…

面試150,數組 / 字符串

27. 移除元素 class Solution:def removeElement(self, nums: List[int], val: int) -> int:# 把不等于 val 的值移動到前面n len(nums)left 0for right in range(n):if nums[right] ! val:nums[left] nums[right]left 1return left26. 刪除有序數組中的重復項 只保留 1…

【江科大STM32】TIM輸入捕獲模式PWMI模式測頻率

一、輸入捕獲測頻率 接線圖&#xff1a; 測信號的輸入引腳為PA6&#xff0c;信號從PA6進來&#xff0c;待測的PWM信號也是STM32自己生成的&#xff0c;輸出引腳是PA0&#xff0c;所以接線這里直接用一根線將PA0引到PA6就可以了。 如果有信號發生器的話&#xff0c;也可以設置成…

湖倉一體化及冷、熱、實時三級存儲

一、湖倉一體化&#xff08;Lakehouse&#xff09; 湖倉一體化&#xff08;Lakehouse&#xff09;是數據湖&#xff08;Data Lake&#xff09;與數據倉庫&#xff08;Data Warehouse&#xff09;的結合&#xff0c;旨在解決傳統數據架構中數據孤島、存儲冗余、計算性能不足等問…

go切片定義和初始化

1.簡介 切片是數組的一個引用&#xff0c;因此切片是引用類型&#xff0c;在進行傳遞時&#xff0c;遵守引用傳遞的機制。切片的使用和數組類似&#xff0c;遍歷切片、訪問切片的元素和切片的長度都一樣。。切片的長度是可以變化的&#xff0c;因此切片是一個可以動態變化的數…

游戲引擎學習第138天

倉庫:https://gitee.com/mrxiao_com/2d_game_3 資產&#xff1a;game_hero_test_assets_003.zip 發布 我們的目標是展示游戲運行時的完整過程&#xff0c;從像素渲染到不使用GPU的方式&#xff0c;我們自己編寫了渲染器并完成了所有的工作。今天我們開始了一些新的內容&#…