探索ArrayList的线程不安全性

文章目录

    • 概要
    • 示例代码
    • 原因
    • 解决
      • 用 synchronized 保证安全添加元素
      • 其他方法
    • 总结

概要

要测试ArrayList的线程不安全性,可以创建多个线程同时对 ArrayList 进行修改操作(如添加、删除元素),并观察是否会引发异常或数据不一致的问题

示例代码

    public static void main(String[] args) throws InterruptedException {List<Integer> list = new ArrayList<>(6000);Thread thread1 = new Thread(() -> {for (int i = 0; i < 3000; i++) {list.add(i);}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 3000; i++) {list.add(-i);}});thread1.start();thread2.start();thread1.join(); // 主线程等待子线程执行结束  主线程才继续执行thread2.join();System.out.println("数组大小:" + list.size());}

执行结果:
在这里插入图片描述

每次结果都不一样,正确的数量因该是2个线程分别添加元素数量总和

原因

在并发环境中,当多个线程同时对 ArrayList 进行操作时,它们之间的竞争可能会导致数据丢失。例如,当多个线程同时调用 add 方法时,可能会出现数据覆盖:如果多个线程同时试图在 ArrayList 中添加元素,它们可能会在同一位置进行写操作,导致之前写入的元素被覆盖。

ArrayList 的 add 操作并不是原子的。在多线程环境下,如果两个线程同时执行 add 操作,它们可能会同时访问和修改 ArrayList 的内部数据结构。这种缺乏原子性的操作会导致竞态条件和数据丢失。

解决

用 synchronized 保证安全添加元素

public synchronized static void addNum(List<Integer> list, int num) {list.add(num);
}public static void main(String[] args) throws InterruptedException {List<Integer> list = new ArrayList<>(6000);Thread thread1 = new Thread(() -> {for (int i = 0; i < 3000; i++) {addNum(list, i);}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 3000; i++) {addNum(list, -i);}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("数组大小: " + list.size());
}

执行结果:
在这里插入图片描述

其他方法

  • Collections.synchronizedList:使用 Collections.synchronizedList(new ArrayList<>()) 来包装 ArrayList,以确保对集合的操作是线程安全的。
  • CopyOnWriteArrayList:使用 CopyOnWriteArrayList,这是一个线程安全的 List 实现,适用于读多写少的场景。
    public static void main(String[] args) throws InterruptedException {List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>(6000));Thread thread1 = new Thread(() -> {for (int i = 0; i < 3000; i++) {list.add(i);}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 3000; i++) {list.add(-i);}});thread1.start();thread2.start();thread1.join(); // 主线程等待子线程执行结束  主线程才继续执行thread2.join();System.out.println("数组大小:" + list.size());}

总结

HahsMap TreeMap 都不是线程安全的,当然 HashSet 由 HashMap 实现,所以 HashSet 线程不安全; TreeSet 由 TreeMap 实现,所以 HashSet 线程不安全。为了解决这个问题,可以使用线程安全的替代品,例如通过 Collections.synchronizedSet() 来包装一个 Set,确保其线程安全。

Collections工具类中的替代品
在这里插入图片描述
写时复制
CopyOnWrite 是一种并发编程策略,常用于实现线程安全的集合类。它的核心思想是在进行写操作时,复制底层数据结构的一个副本,并在新副本上执行修改操作,旧的副本仍然保持不变,供当前正在进行的读操作使用。这种策略适用于读操作频繁、写操作较少的场景。
在这里插入图片描述


❤觉得有用的可以留个关注~~❤

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/415556.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unity游戏开发——标记物体 一目了然

Unity游戏开发:标记物体,让开发变得一目了然 “好读书&#xff0c;不求甚解&#xff1b;每有会意&#xff0c;便欣然忘食。” 本文目录&#xff1a; Unity游戏开发 Unity游戏开发:标记物体,让开发变得一目了然前言1. 什么是Tag&#xff1f;2. Unity中如何添加和管理Tag步骤1&am…

微电网管理系统

微电网管理系统 1. 相关概念简介 基本概念及分析意义&#xff1a; 微电网基本概念&#xff1a;微电网&#xff08;MG&#xff09;由分布式电源、用电负荷、能量管理系统等组成&#xff0c;是一个能够基本实现内部电力电量平衡的供用电系统。 通过整合分布式电源、储能、负荷…

阿里巴巴数学竞赛成绩未公布:背后的权衡与期待

文 | 头部财经首席评论员白立新 发布 | 头部财经 top168.com 导语&#xff1a;2024 年阿里巴巴数学竞赛成绩迟未公布&#xff0c;引发广泛猜测。中专生姜萍的表现备受瞩目&#xff0c;达摩院陷入两难困境。这场竞赛结果的公布&#xff0c;关乎多方利益与社会影响&#xff0c;…

学习之git

github 创建远程仓库 代码推送 Push 代码拉取 Pull 代码克隆 Clone SSH免密登录 Idea集成GitHubGitee码云 码云创建远程仓库 Idea集成Gitee码云 码云连接Github进行代码的复制和迁移GitLab gitlab服务器的搭建和部署 Idea集成GitLabgit概述 一切皆本地 版本控制工具 集中…

服务器数据恢复—磁盘坏扇区导致raid6阵列崩溃的数据恢复案例

服务器存储数据恢复环境&#xff1a; 一台存储中有一组由12块SAS硬盘组建的raid6磁盘阵列&#xff0c;划分了1个卷&#xff0c;由数台Vmware ESXI主机共享存储。卷中存放了大量的Windows系统虚拟机。这些虚拟机系统盘大小一致&#xff0c;数据盘大小不确定&#xff0c;数据盘都…

8连接数据与决策:信息系统基础概念解读

信息系统概述 信息系统是由计算机硬件、网络和通信设备、计算机软件、信息资源、信息用户和规章制度组成的以处理信息流为目的的人机一体化系统。 信息系统的5个基本功能&#xff1a;输入、存储、处理、输出和控制。 信息系统的性质影响着系统开发者和系统用户的知识需求。“…

vue大数据展示之虚拟列表

面试代码学习 父组件&#xff1a; <template><div class"box"><!--items总条数、 size数据高度、 shownumber每次渲染数据--><list :items"items" :size"60" :shownumber"10"></list></div><…

生活方式对人健康影响非常大 第三篇

身体健康因素中 生活方式占到60% 赶紧去调整自己哪错了 上游的生活方式管理 是药三分毒 药物会影响身体肝肾功能,代谢 所以你要去找上游到底是我哪错了 短板越多 个健康状态越差 饮食管理是生活方式管理中难度最大的 原则1:与基因相对应相平衡 只吃素 会导致大脑萎…

并发集合(二):CopyOnWriteArrayList

1、CopyOnWriteArrayList介绍 CopyOnWriteArrayList 是一个线程安全的ArrayList。 CopyOnWriteArrayList 是基于Lock锁和线程副本的形式来保证线程安全的&#xff0c; 在写数据时&#xff0c;先获取Lock锁&#xff0c;然后复制一个副本&#xff0c;添加数据时&…

Qt 按钮图片文字上下结构(纯qss实现)

效果图 实现 QSS QPushButton {border-radius: 6px;opacity: 1;font: 9pt "微软雅黑";color: #333;padding-top:20px;background: url(:/images/ico_un_collected.png) top center no-repeat; } QPushButton:hover {color: #408cff; } QPushButton:pressed {color: …

14、Django Admin的“Action(动作)”中添加额外操作

如图红框增加操作 将以下代码添加到HeroAdmin类中 actions ["mark_immortal"] def mark_immortal(self, request, queryset):queryset.update(is_immortalTrue) 修改后完整代码如下&#xff1a; admin.register(Hero) class HeroAdmin(admin.ModelAdmin):list_di…

固定式测斜仪在铁路防滑坡中的应用

在铁路建设与运营过程中&#xff0c;滑坡作为一种严重的地质灾害&#xff0c;不仅威胁着工程安全&#xff0c;还直接关系到人民生命财产的安全。面对滑坡频发&#xff0c;特别是南方铁路干线所处的地质灾害易发区域&#xff0c;如何有效识别、监测并预防滑坡&#xff0c;成为铁…

【C++从练气到飞升】19---哈希:哈希冲突 | 哈希函数 | 闭散列 | 开散列

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书&#x1f389; 目录 ⛳️推荐 一、unordered 系列关联式容器 二、unordered_map 1.1 unordered_map 介绍 1.2 unordered_map 的…

NoSql数据库 - Redis Cluster集群详解及案例实现

Redis Cluster集群&#xff08;无中心化设计&#xff09; 1.1 Redis Cluster 工作原理 在哨兵sentinel机制中&#xff0c;可以解决redis高可用问题&#xff0c;即当master故障后可以自动将slave提升为master&#xff0c;从而可以保证redis服务的正常使用&#xff0c;但是无法…

HIOKI功率分析仪PW3390-03

HIOKI功率分析仪PW3390-03 实现高级别的功率基本精度0.04%rdg.0.05%f.s •200kHz的测量频带&#xff0c;高频也很稳定的振幅和相位精度 •实现机身小型/轻巧化&#xff0c;满足现场和研究室的高精度测量 •50ms高精度高速运算过渡状态的功率&#xff0c;同时并行运算谐波分析、…

Spring优缺点和SpringBoot基础和搭建

前言 Spring框架是一个流行的Java企业级开发框架&#xff0c;旨在简化应用程序开发。它的核心特性包括依赖注入和面向切面编程&#xff0c;提供了灵活性和强大的社区支持。然而&#xff0c;Spring也存在学习曲线陡峭和配置复杂等缺点。 Spring Boot是基于Spring的项目&#x…

观测云核心技术解密:eBPF Tracing 实现原理

前言 eBPF 是一种强大的内核技术&#xff0c;允许在内核中安全地执行自定义代码。通过 eBPF&#xff0c;开发者可以在不修改内核源码的情况下&#xff0c;对内核功能进行扩展和监控。eBPF Tracing 利用这一技术&#xff0c;对系统调用、内核函数等进行跟踪&#xff0c;从而实现…

OpenCV下的无标定校正(stereoRectifyUncalibrated)

OpenCV下的无标定校正(stereoRectifyUncalibrated) 文章目录 1. 杂话2. 无标定校正2.1 先看代码2.2 一点解释2.3 findFundamentalMat参数2.4 stereoRectifyUncalibrated参数 3. 矫正结果 1. 杂话 咱们在之前的帖子里面讲了一些比较常规的标定和校正OpenCV下的单目标定&#xff…

解决bug: RuntimeError: Address already in use,一个linux下pytorch多卡训练tcp端口占用的bug

时间&#xff1a;2024.9.3 1&#xff09;bug&#xff1a; self._store TCPStore( # type: ignore[call-arg] RuntimeError: Address already in use2&#xff09;原因分析 linux下pytorch多卡训练深度学习模型&#xff0c;训练中途暂停训练&#xff0c;但仍有进程占用某个端…

OcrLiteNcnn:Windows环境打包及Java调用

目录结构 前言cmake安装源码下载说明Windows源码编译执行“cmake -DCMAKE_BUILD_TYPE=Release ..”执行“cmake --build . --config Release -- -m:6”编译完成识别图片命令行调用Java调用前言 Java实现OCR识别图片中的文字,小编先前整理过一篇在Linux环境中基于“ChineseOcr…