写时复制的List和Set

保证线程安全的思路:

一种是锁,使用synchronized或ReentrantLock;另外一种是循环CAS,写时复制体现了保证线程安全的另一种思路。

锁和循环CAS都是控制对同一个资源的访问冲突,而写时复制通过复制资源减少冲突。对于绝大部分访问都是读,且有大量并发线程要求读,只有个别线程进行写,且只是偶尔写的场合,写时复制就是一种很好的解决方案。

 

Copy-On-Write即写时复制,或称写时拷贝,这是解决并发问题的一种重要思路。

 

CopyOnWriteArrayList

CopyOnWriteArrayList实现了List接口,它的用法与其他List(如ArrayList)基本是一样的。CopyOnWriteArrayList的特点如下:

❑ 它是线程安全的,可以被多个线程并发访问;

❑ 它的迭代器不支持修改操作,但也不会抛出ConcurrentModificationException;

❑ 它以原子方式支持一些复合操作。

CopyOnWriteArrayList的内部也是一个数组,但这个数组是以原子方式被整体更新的。每次修改操作,都会新建一个数组,复制原数组的内容到新数组,在新数组上进行需要的修改,然后以原子方式设置内部的数组引用,这就是写时复制。

所有的读操作,都是先拿到当前引用的数组,然后直接访问该数组。在读的过程中,可能内部的数组引用已经被修改了,但不会影响读操作,它依旧访问原数组内容。

换句话说,数组内容是只读的,写操作都是通过新建数组,然后原子性地修改数组引用来实现的。

 

每次修改都要创建一个新数组,然后复制所有内容,这听上去是一个难以令人接受的方案,如果数组比较大,修改操作又比较频繁,可以想象,CopyOnWriteArrayList的性能是很低的。事实确实如此,CopyOnWriteArrayList不适用于数组很大且修改频繁的场景。它是以优化读操作为目标的,读不需要同步,性能很高,但在优化读的同时牺牲了写的性能。

 

CopyOnWriteArraySet

CopyOnWriteArraySet实现了Set接口,不包含重复元素

由于CopyOnWriteArraySet是基于CopyOnWriteArrayList实现的,所以与之前介绍过的Set的实现类如HashSet/TreeSet相比,它的性能比较低,不适用于元素个数特别多的集合

 

 

CopyOnWriteArrayList和CopyOnWriteArraySet适用于读远多于写、集合不太大的场合,它们采用了写时复制,这是计算机程序中一种重要的思维和技术。

写时复制是一种重要的思维,用于各种计算机程序中,比如操作系统内部的进程管理和内存管理。在进程管理中,子进程经常共享父进程的资源,只有在写时才复制。在内存管理中,当多个程序同时访问同一个文件时,操作系统在内存中可能只会加载一份,只有程序要写时才会复制,分配自己的内存,复制可能也不会全部复制,只会复制写的位置所在的

 

 

参考: Java编程的逻辑 17.1 写时复制的List和Set

 

posted @   草木物语  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2019-01-27 ajax 跨域 springboot
2018-01-27 js,jquery 获取滚动条高度和位置, 元素距顶部距离
2018-01-27 java 向上转型与向下转型
2018-01-27 Java 判断相等
点击右上角即可分享
微信分享提示