欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java常用集合與映射的線程安全問(wèn)題小結(jié)

 更新時(shí)間:2025年04月11日 10:01:29   作者:jiajia651304  
本文給大家介紹Java常用集合與映射的線程安全問(wèn)題小結(jié),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

Java常用集合與映射的線程安全問(wèn)題深度解析

一、線程安全基礎(chǔ)認(rèn)知

在并發(fā)編程環(huán)境下,當(dāng)多個(gè)線程同時(shí)操作同一集合對(duì)象時(shí),若未采取同步措施,可能導(dǎo)致以下典型問(wèn)題:

  • 數(shù)據(jù)競(jìng)爭(zhēng):多個(gè)線程同時(shí)修改數(shù)據(jù)導(dǎo)致結(jié)果不可預(yù)測(cè)
  • 狀態(tài)不一致:部分線程看到集合的中間狀態(tài)
  • 內(nèi)存可見(jiàn)性:線程本地緩存與主內(nèi)存數(shù)據(jù)不同步
  • 死循環(huán)風(fēng)險(xiǎn):特定操作引發(fā)無(wú)限循環(huán)(如JDK7的HashMap擴(kuò)容)

二、典型非線程安全集合問(wèn)題分析

1. ArrayList的并發(fā)陷阱

// 錯(cuò)誤示例
List<Integer> list = new ArrayList<>();
ExecutorService pool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
    pool.execute(() -> list.add(new Random().nextInt()));
}
// 運(yùn)行結(jié)果可能包含:元素丟失、size值異常、數(shù)組越界異常等

問(wèn)題根源

  • add()方法非原子操作:elementData[size++] = e
  • 多線程同時(shí)觸發(fā)擴(kuò)容導(dǎo)致數(shù)組拷貝覆蓋
  • size變量可見(jiàn)性問(wèn)題

2. HashMap的并發(fā)災(zāi)難

Map<String, Integer> map = new HashMap<>();
// 并發(fā)執(zhí)行put操作可能導(dǎo)致:
// 1. JDK7及之前版本:環(huán)形鏈表導(dǎo)致CPU 100%
// 2. JDK8+版本:數(shù)據(jù)丟失或size計(jì)數(shù)錯(cuò)誤
// 3. 迭代時(shí)ConcurrentModificationException

底層機(jī)制

  • 哈希桶結(jié)構(gòu)在擴(kuò)容時(shí)產(chǎn)生鏈表斷裂
  • 頭插法(JDK7)與尾插法(JDK8)差異
  • 沒(méi)有同步機(jī)制的Entry數(shù)組操作

3. HashSet的隱藏風(fēng)險(xiǎn)

Set<Integer> set = new HashSet<>();
// 本質(zhì)是HashMap的包裝類,所有線程安全問(wèn)題與HashMap一致
// add()方法并發(fā)調(diào)用時(shí)可能產(chǎn)生元素丟失

三、線程安全解決方案對(duì)比

1. 同步包裝方案

// 使用Collections工具類
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, Object> syncMap = Collections.synchronizedMap(new HashMap<>());
// 特征:
// 1. 所有方法使用synchronized同步塊
// 2. 迭代器需要手動(dòng)同步
// 3. 鎖粒度大,性能較差

2. 傳統(tǒng)線程安全集合

// Vector/Hashtable方案
Vector<String> vector = new Vector<>(); 
Hashtable<String, Integer> table = new Hashtable<>();
// 缺點(diǎn):
// 1. 全表鎖導(dǎo)致吞吐量低
// 2. 已逐漸被并發(fā)容器取代

3. 現(xiàn)代并發(fā)容器(java.util.concurrent包)

3.1 CopyOnWriteArrayList

List<String> cowList = new CopyOnWriteArrayList<>();
// 實(shí)現(xiàn)原理:
// 1. 寫(xiě)操作時(shí)復(fù)制新數(shù)組
// 2. 最終一致性保證
// 適用場(chǎng)景:讀多寫(xiě)少(如白名單配置)

3.2 ConcurrentHashMap

Map<String, Object> concurrentMap = new ConcurrentHashMap<>();
// JDK8+實(shí)現(xiàn)特點(diǎn):
// 1. 分段鎖升級(jí)為CAS+synchronized
// 2. 節(jié)點(diǎn)鎖粒度(鎖單個(gè)哈希桶)
// 3. 支持并發(fā)度設(shè)置

3.3 ConcurrentSkipListMap

NavigableMap<String, Integer> skipMap = new ConcurrentSkipListMap<>();
// 特征:
// 1. 基于跳表實(shí)現(xiàn)的有序Map
// 2. 無(wú)鎖讀取,寫(xiě)入使用CAS

四、并發(fā)容器實(shí)現(xiàn)原理剖析

1. CopyOnWriteArrayList寫(xiě)時(shí)復(fù)制機(jī)制

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}

2. ConcurrentHashMap并發(fā)控制

JDK8關(guān)鍵實(shí)現(xiàn)

  • 哈希桶數(shù)組+鏈表/紅黑樹(shù)
  • CAS操作實(shí)現(xiàn)無(wú)鎖化讀取
  • synchronized鎖單個(gè)節(jié)點(diǎn)
  • size計(jì)算采用LongAdder機(jī)制

3. 并發(fā)隊(duì)列實(shí)現(xiàn)對(duì)比

隊(duì)列類型鎖機(jī)制適用場(chǎng)景
ConcurrentLinkedQueueCAS無(wú)鎖高并發(fā)生產(chǎn)者消費(fèi)者模式
LinkedBlockingQueueReentrantLock雙鎖有界阻塞隊(duì)列
ArrayBlockingQueue單ReentrantLock固定容量隊(duì)列

五、最佳實(shí)踐與注意事項(xiàng)

1. 選型決策指南

  • 讀多寫(xiě)少:CopyOnWrite系列
  • 高并發(fā)寫(xiě)入:ConcurrentHashMap
  • 強(qiáng)一致性需求:同步包裝類+手動(dòng)鎖
  • 有序性要求:ConcurrentSkipListMap

2. 常見(jiàn)誤區(qū)規(guī)避

  • 錯(cuò)誤認(rèn)知:認(rèn)為Collections.synchronizedXXX比并發(fā)容器更安全
  • 迭代器問(wèn)題:未對(duì)同步集合的迭代器加鎖
  • 復(fù)合操作漏洞:即使使用線程安全集合,多個(gè)操作仍需同步
// 錯(cuò)誤示例:即使使用ConcurrentHashMap仍需同步
if (!map.containsKey(key)) {
    map.put(key, value); // 非原子操作
}
// 正確寫(xiě)法:
map.putIfAbsent(key, value);

3. 性能優(yōu)化建議

  • 預(yù)估ConcurrentHashMap初始容量減少擴(kuò)容
  • 避免在CopyOnWriteArrayList中使用超大數(shù)組
  • 合理設(shè)置并發(fā)級(jí)別(ConcurrentHashMap構(gòu)造函數(shù))
  • 使用批量操作方法(如putAll)

六、高級(jí)話題擴(kuò)展

1. 弱一致性迭代器

  • ConcurrentHashMap的迭代器反映創(chuàng)建時(shí)的狀態(tài)
  • 不保證迭代過(guò)程中數(shù)據(jù)變化可見(jiàn)

2. 原子復(fù)合操作

// 使用merge方法實(shí)現(xiàn)原子計(jì)數(shù)
ConcurrentHashMap<String, Long> counterMap = new ConcurrentHashMap<>();
counterMap.merge("key", 1L, Long::sum);

3. 分段鎖的演進(jìn)

  • JDK7的Segment分段鎖(默認(rèn)16段)
  • JDK8的Node粒度鎖(鎖單個(gè)哈希桶)

總結(jié)與建議

  • 嚴(yán)格區(qū)分場(chǎng)景:根據(jù)讀寫(xiě)比例、一致性要求選擇容器
  • 理解實(shí)現(xiàn)原理:避免誤用并發(fā)容器特性
  • 組合使用鎖機(jī)制:必要時(shí)搭配ReentrantLock使用
  • 監(jiān)控工具輔助:使用JConsole觀察容器爭(zhēng)用情況

開(kāi)發(fā)者應(yīng)當(dāng)建立以下意識(shí):

  • 沒(méi)有絕對(duì)線程安全的容器,只有相對(duì)安全的操作方式
  • 并發(fā)問(wèn)題往往在高壓場(chǎng)景下暴露
  • 充分測(cè)試是驗(yàn)證線程安全性的必要手段

通過(guò)合理選擇并發(fā)容器并遵循最佳實(shí)踐,可以顯著降低多線程環(huán)境下的集合操作風(fēng)險(xiǎn),構(gòu)建高性能高可靠的Java應(yīng)用系統(tǒng)。

到此這篇關(guān)于Java常用集合與映射的線程安全的文章就介紹到這了,更多相關(guān)java集合與映射內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring @Primary作用和實(shí)現(xiàn)原理詳解

    Spring @Primary作用和實(shí)現(xiàn)原理詳解

    今天分享一下Spring中的@Primary注解,Primary的意思是主要的,我們?cè)谑褂胹pring的時(shí)候,難免會(huì)定義多個(gè)類型相同的bean,這時(shí)候如果不采取一些方法,那么是無(wú)法正常使用bean的,所以本就給大家介紹Spring @Primary的作用和實(shí)現(xiàn)原理
    2023-07-07
  • spring boot中nativeQuery的用法

    spring boot中nativeQuery的用法

    這篇文章主要介紹了spring boot中nativeQuery的作用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07
  • Java多線程之線程通信生產(chǎn)者消費(fèi)者模式及等待喚醒機(jī)制代碼詳解

    Java多線程之線程通信生產(chǎn)者消費(fèi)者模式及等待喚醒機(jī)制代碼詳解

    這篇文章主要介紹了Java多線程之線程通信生產(chǎn)者消費(fèi)者模式及等待喚醒機(jī)制代碼詳解,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • 基于SpringBoot + Android實(shí)現(xiàn)登錄功能

    基于SpringBoot + Android實(shí)現(xiàn)登錄功能

    在移動(dòng)互聯(lián)網(wǎng)的今天,許多應(yīng)用需要通過(guò)移動(dòng)端實(shí)現(xiàn)與服務(wù)器的交互功能,其中登錄是最常見(jiàn)且基礎(chǔ)的一種功能,本篇博客將詳細(xì)介紹如何使用 Spring Boot 和 Android 實(shí)現(xiàn)一個(gè)完整的登錄功能,需要的朋友可以參考下
    2024-11-11
  • Java進(jìn)程內(nèi)緩存框架EhCache詳解

    Java進(jìn)程內(nèi)緩存框架EhCache詳解

    這篇文章主要介紹了Java進(jìn)程內(nèi)緩存框架EhCache,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-12-12
  • mybatis plus條件構(gòu)造器queryWrapper、updateWrapper

    mybatis plus條件構(gòu)造器queryWrapper、updateWrapper

    這篇文章主要介紹了mybatis plus條件構(gòu)造器queryWrapper、updateWrapper,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java實(shí)現(xiàn)圖片模糊效果詳解

    Java實(shí)現(xiàn)圖片模糊效果詳解

    圖片模糊是圖像處理中的一種常見(jiàn)效果,它通過(guò)平均周圍像素的顏色來(lái)使圖像變得模糊,下面我們來(lái)看看如何使用Swing庫(kù)實(shí)現(xiàn)圖片模糊效果吧
    2025-02-02
  • Spring?Boot?集成?Swagger2構(gòu)建?API文檔

    Spring?Boot?集成?Swagger2構(gòu)建?API文檔

    這篇文章主要介紹了Spring?Boot?集成?Swagger2構(gòu)建?API文檔,通過(guò)使用?Swagger,我們只需要按照它所給定的一系列規(guī)范去定義接口以及接口的相關(guān)信息,然后它就能幫我們自動(dòng)生成各種格式的接口文檔,方便前后端開(kāi)發(fā)者進(jìn)行前后端聯(lián)調(diào),下文需要的朋友可以參考一下
    2022-03-03
  • Java字符串相關(guān)類使用方法詳解

    Java字符串相關(guān)類使用方法詳解

    String、StringBuilder、StringBuffer還傻傻分不清,下面這篇文章主要給大家介紹了關(guān)于Java字符串相關(guān)類使用的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • Mybatis-Plus自動(dòng)填充更新操作相關(guān)字段的實(shí)現(xiàn)

    Mybatis-Plus自動(dòng)填充更新操作相關(guān)字段的實(shí)現(xiàn)

    數(shù)據(jù)庫(kù)表中應(yīng)該都要有create_time、update_time字段;那么在開(kāi)發(fā)中,對(duì)于這些共有字段的處理應(yīng)該要進(jìn)行統(tǒng)一,這樣就可以簡(jiǎn)化我們的開(kāi)發(fā)過(guò)程。那么本文就對(duì)Mybatis-Plus中的字段自動(dòng)填充進(jìn)行記錄
    2021-11-11

最新評(píng)論