当前位置: 首页 > news >正文

Java集合之【CopyOnWrite和Collections.synchronizedList()的区别】

CopyOnWriteArrayList 介绍

什么是 CopyOnWriteArrayList

适合读多写少的场景

是一个线程安全的List实现,特点是写时复制

CopyOnWriteArrayList进行修改操作(如add,set,remove)的时候,会复制原数组的值到创建的新数组中,并且读操作的时候不加锁,写操作会加锁

CopyOnWriteArrayList 的读操作

不加锁,每次写操作都会创建并复制新的数组,所以读数据的时候不会发生冲突,所以读操作不需要加锁,这样读操作的效率就会很高

CopyOnWriteArrayList 的写操作

加锁,会复制并创建新数组,因此开销大,数据量大的时候,在同一时刻会存在两倍大小的List大小的内存占用

public E set(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();try {// ...CODE...} finally {lock.unlock();}
}

CopyOnWriteArrayList 会出现读写不一致吗?

会,CopyOnWriteArrayList 使用的是弱一致性。

通过设计上的取舍

  • 换取高性能的读操作

  • 保证线程安全

  • 不保证实时一致性

因此CopyOnWriteArrayList 适合读多写少的场景

代码检测

public class CopyOnWriteDemo {public static void main(String[] args) throws InterruptedException {List<String> list = new CopyOnWriteArrayList<>();list.add("A");list.add("B");// 线程:不停读Thread reader = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("Reader: " + list);try {Thread.sleep(200);} catch (InterruptedException ignored) {}}});// 线程:写入数据Thread writer = new Thread(() -> {try {Thread.sleep(300);} catch (InterruptedException ignored) {}list.add("C");System.out.println("Writer added C");});reader.start();writer.start();reader.join();writer.join();}
}

join():让主线程等待子线程,避免出现数据不一致,或主线程结束了子线程才结束

输出结果:

Reader: [A, B]
Writer added C
Reader: [A, B, C]
Reader: [A, B, C]
Reader: [A, B, C]
Reader: [A, B, C]

显然:

写操作对应的数组是“新”数组

读操作对应的数组是“旧”数组

写完成之后就将旧数组替换成新数组

Collections.synchronizedList() 介绍

Collections的一个包装方法,可以将List转换为线程安全的版本,对每个方法(set,get,add,remove) 都会添加一个sychronized关键字,进行同步锁,从而保证线程安全

适用场景

需要将ArrayList<>()快速转换成为线程安全的版本,以及是在简单将List转换为线程安全版本临时使用的场景

List<String> list = Collections.synchronizedList(new ArrayList<>());

缺点

缺点就是不适用于高并发的场景,因为每个操作都会使用同一个sychronized同步锁

源码所示:

 public E get(int index) {synchronized (mutex) {return list.get(index);}}
public E set(int index, E element) {synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {synchronized (mutex) {return list.remove(index);}
}

mutex: 一般指的是this,也就是说所有的读写都是用同一把锁

源码:

final Collection<E> c;  // Backing Collection
final Object mutex;     // Object on which to synchronizeSynchronizedCollection(Collection<E> c) {this.c = Objects.requireNonNull(c);mutex = this;
}

所以Collections.synchronizedList()是不适合在高并发场景下使用的

总结

特性 synchronizedList CopyOnWriteArrayList
线程安全方式 synchronized 锁 写时复制(读无锁)
读操作 加锁(慢) 无锁(快)
写操作 加锁(较快) 复制数组(很慢)
适用场景 写多读少 读多写少
迭代器 不安全,需手动 synchronized 安全,不会抛 CME
http://icebutterfly214.com/news/46668/

相关文章:

  • Sora 2 Cameo多角色上传+Remix二创功能API接入教程,史低0.08/条
  • 基于MIMO系统的SCMA稀疏码多址接入和MPA消息传递算法matlab仿真
  • 一次尝试,3个小时90元的主机游玩和F1电影
  • [GESP202506 二级] 幂和数
  • 2025 年锚具厂家 TOP 企业品牌推荐排行榜,预应力锚具 / 五孔锚具 / 低回缩锚具 / 张拉锚具 / 固定端锚具 / 桥梁预应力锚具 / 边坡锚具公司推荐!
  • 论文速读 | 2025年11月
  • Flask+Celery+Blueprint
  • hadoop linux 安装
  • 2025年11月学习机榜单:打破智商税偏见,十大提分机型实证推荐
  • 题解:uoj632【UR #21】挑战最大团
  • Hier-SLAM++ (2) MeshGPT:仅使用解码器Transformer生成三角形网格 - MKT
  • QQ流量分析
  • 20232404 2025-2026-1 《网络与系统攻防技术》实验六实验报告
  • 复合剩余问题
  • 自定义yml激活进本地通用yml
  • AT_jsc2019_qual_e Card Collector
  • P9534 [YsOI2023] 广度优先遍历
  • 美国研究生申请中介怎么选?2025高性价比机构测评推荐,藤校录取率超同行的机构盘点
  • 版本号
  • 缓冲区计算问题
  • 大威德
  • 2025年美国留学中介哪家强,藤校申请/全程规划/背景提升/签证辅导/求职赋能优质机构推荐
  • 2025留学中介哪家好?厚仁/新通等5大品牌,多国联申/offer保障/名校申请/求职赋能全覆盖
  • 2025靠谱留学机构推荐TOP5!美国/英国/澳洲多国申请,高录取率机构榜单
  • 04-import 和 export
  • 堆贪心
  • 算法课 PA2 T1
  • 在AI技术唾手可得的时代,挖掘新需求成为制胜关键——某知名智能支付协议需求探索
  • 2025年茉莉花茶定做厂家权威推荐榜单:青梅绿茶/无糖茶/乌龙茶源头厂家精选
  • winform中消息机制使用CommunityToolkit.Mvvm