【并发编程篇】解决线程安全问题 — CopyOnWriteArrayList

2023-12-29 14:04

本文主要是介绍【并发编程篇】解决线程安全问题 — CopyOnWriteArrayList,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 🍔情景引入
    • 🌺报错了,解决方案
      • ⭐方法一
      • ⭐方法二
      • ⭐方法三

在这里插入图片描述

🍔情景引入

我们看下面这段代码
在这里插入图片描述

现在这段代码是线程安全的,如果我们修改代码,修改为10个线程

在这里插入图片描述
报错了
我们看报错信息
在这里插入图片描述
是并发修改异常

🌺报错了,解决方案

在刚才的案例中,我们看到,并发下,ArrayList是不安全的,下面将提供两种解决方法

⭐方法一

使用vector

package org.Test6;import java.util.List;
import java.util.UUID;
import java.util.Vector;public class ListTest {public static void main(String[] args) {List<String> list=new Vector<>();for (int i = 0; i < 10; i++) {new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,5));System.out.println(list);},String.valueOf(i)).start();}}
}

在这里插入图片描述

⭐方法二

我们使用其他工具类,使用Collections
使用 Collections.synchronizedList() 方法将普通的 ArrayList 转换为一个线程安全的 List 集合。通过对 list 进行同步化操作,可以保证在多线程环境下对 list 的访问是线程安全的。

Collections.synchronizedList() 方法返回一个线程安全的 List 对象,该对象内部使用同步机制来确保多线程环境下的安全访问。具体来说,它会对 List 的各种操作(如添加、删除、获取等)进行同步化处理,以避免并发修改引发的线程安全问题,比如数据不一致或异常。

好处如下:

  • 线程安全:通过使用 Collections.synchronizedList() 方法,可以确保多个线程同时访问 list 时不会出现数据竞争和不一致的问题。这样可以提高程序的健壮性和可靠性。
  • 方便转换:通过使用 Collections.synchronizedList() 方法,可以方便地将普通的集合类转换为线程安全的集合类,无需手动编写同步代码。

需要注意的是,虽然 Collections.synchronizedList() 方法可以确保对集合的基本操作是线程安全的,但在进行复合操作时仍然需要额外的同步措施。例如,在循环遍历 list 并进行复合操作时,仍需要使用外部的同步机制,比如使用 synchronized 关键字或 Lock 接口。

此外,如果只是在单线程环境下使用集合,或者可以保证对集合的访问是单线程的,那么不一定需要使用线程安全的集合类。因为线程安全的集合类在性能上会有一些额外开销,所以在单线程环境下使用普通的集合类可能更加高效。

package org.Test6;import java.util.*;public class ListTest {public static void main(String[] args) {List<String> list= Collections.synchronizedList(new ArrayList<>());for (int i = 0; i < 10; i++) {new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,5));System.out.println(list);},String.valueOf(i)).start();}}
}

在这里插入图片描述

⭐方法三

使用juc包下的CopyOnWriteArrayList方法

CopyOnWriteArrayList 是一个线程安全的 List 集合,它的特点是在进行写操作时会复制一份原有的数组,并在新的数组上进行修改,从而避免了并发修改导致的问题。因此,CopyOnWriteArrayList 是一种适用于读多写少场景下的线程安全集合。

CopyOnWriteArrayList 的读取操作不需要加锁,因为读取时直接读取原数组中的数据即可。而对于写操作,由于修改的是新的数组,因此写操作不会影响到正在读取旧数组的线程,从而避免了并发修改导致的问题。当写操作完成后,CopyOnWriteArrayList 会将新数组替换旧数组,从而使得所有线程都能读取到新的数据。

写入的时候避免覆盖,造成数据问题

package org.Test6;import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;public class ListTest {public static void main(String[] args) {List<String> list= new CopyOnWriteArrayList<>();for (int i = 0; i < 10; i++) {new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,5));System.out.println(list);},String.valueOf(i)).start();}}
}

在这里插入图片描述

在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!

在这里插入图片描述

这篇关于【并发编程篇】解决线程安全问题 — CopyOnWriteArrayList的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/549656

相关文章

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异

Spring Security 前后端分离场景下的会话并发管理

《SpringSecurity前后端分离场景下的会话并发管理》本文介绍了在前后端分离架构下实现SpringSecurity会话并发管理的问题,传统Web开发中只需简单配置sessionManage... 目录背景分析传统 web 开发中的 sessionManagement 入口ConcurrentSess

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

Java报错:org.springframework.beans.factory.BeanCreationException的五种解决方法

《Java报错:org.springframework.beans.factory.BeanCreationException的五种解决方法》本文解析Spring框架中BeanCreationExce... 目录引言一、问题描述1.1 报错示例假设我们有一个简单的Java类,代表一个用户信息的实体类:然后,

Linux部署中的文件大小写问题的解决方案

《Linux部署中的文件大小写问题的解决方案》在本地开发环境(Windows/macOS)一切正常,但部署到Linux服务器后出现模块加载错误,核心原因是Linux文件系统严格区分大小写,所以本文给大... 目录问题背景解决方案配置要求问题背景在本地开发环境(Windows/MACOS)一切正常,但部署到