【并发编程篇】解决线程安全问题 — 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

相关文章

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约

解决tomcat启动时报Junit相关错误java.lang.ClassNotFoundException: org.junit.Test问题

《解决tomcat启动时报Junit相关错误java.lang.ClassNotFoundException:org.junit.Test问题》:本文主要介绍解决tomcat启动时报Junit相... 目录tomcat启动时报Junit相关错误Java.lang.ClassNotFoundException

解决Maven项目报错:failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.13.0的问题

《解决Maven项目报错:failedtoexecutegoalorg.apache.maven.plugins:maven-compiler-plugin:3.13.0的问题》这篇文章主要介... 目录Maven项目报错:failed to execute goal org.apache.maven.pl

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

MySQL主从同步延迟问题的全面解决方案

《MySQL主从同步延迟问题的全面解决方案》MySQL主从同步延迟是分布式数据库系统中的常见问题,会导致从库读取到过期数据,影响业务一致性,下面我将深入分析延迟原因并提供多层次的解决方案,需要的朋友可... 目录一、同步延迟原因深度分析1.1 主从复制原理回顾1.2 延迟产生的关键环节二、实时监控与诊断方案

SQLyog中DELIMITER执行存储过程时出现前置缩进问题的解决方法

《SQLyog中DELIMITER执行存储过程时出现前置缩进问题的解决方法》在SQLyog中执行存储过程时出现的前置缩进问题,实际上反映了SQLyog对SQL语句解析的一个特殊行为,本文给大家介绍了详... 目录问题根源正确写法示例永久解决方案为什么命令行不受影响?最佳实践建议问题根源SQLyog的语句分

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二: