IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java软件开发 | 高并发编程篇之——安全访问的集合(2) -> 正文阅读

[Java知识库]Java软件开发 | 高并发编程篇之——安全访问的集合(2)

上一期的开发干货文章,我们和大家分享了关于“支持并发安全访问的集合”中的第一个点:ConcurrentHashMap。文中对于ConcurrentHashMap的原理介绍及实现方式都做了相应阐述,相信大家应该都有所掌握。

今天,我们来看“支持并发安全访问的集合”的第二个知识点:

②CopyOnWriteArrayList和CopyOnWriteArrayList

因为CopyOnWriteArraySet底层也是使用了CopyOnWriteArrayList来实现的,所以本篇文章以CopyOnWriteArrayList讲解为主。

CopyOnWriteArrayList是JDK1.5之后提供的一个List接口的实现子类,位于java.util.concurrent并发包下,它是一个线程安全的变体ArrayList 的实现。其实CopyOnWriteArrayList在我们的一些开发场景下就有使用,只不过我们自己很少使用它而已,例如:我们JDBC操作数据库的时候注册的Driver驱动信息就是存放在CopyOnWriteArrayList里来保证多线程安全的。

图片

CopyOnWriteArrayList重点突出的是CopyOnWrite(写入时复制),即当有Write(add、set、remove等)操作的时候进行数组的Copy复制新的数组副本来实现,是一种读写分离的并发策略。

查看源码分析其原理:

图片

首先看到的是CopyOnWriteArrayList里面的数据都是存放在一个被volatile修饰的数组中,即底层是动态数组的实现,只不过这个数组可以保证线程操作的可见性和代码的有序性执行。并且这里看到有个ReentrantLock所以我们猜测底层可能使用了Lock锁的实现。

再来看下其write操作代码:

图片

图片

图片

我们发现确实使用了不被序列化的ReentrantLock锁来实现的线程同步,并且锁的粒度大几乎囊括了整个操作方法,这里没有考虑使用synchronized的原因是因为lock锁操作起来更加灵活,我们可以看到它在try…finally结构中不管是否操作成功都会释放锁不会导致锁的阻塞。

CopyOnWriteArrayList设计的好处:

1.线程安全操作和效率

底层使用了ReentrantLock保证了增删改write操作的线程安全性,并且相比于Vector每个操作方法都通过synchronized同步方法处理来说,CopyOnWriteArrayList的同步锁更加灵活,并且CopyOnWriteArrayList读操作是没有锁的,所以读操作效率要高于Vector。

2.读写分离

CopyOnWriteArrayList其遍历操作和写操作是作用再不同的数组中,遍历是使用了其声明的Object[] array进行遍历(其迭代器也不支持write操作),而写的时候是新创建的数组操作所以不会出现线程安全的问题。

这点List则不行,List在遍历时,如果中途有别的线程对list数据进行修改,则会抛出ConcurrentModificationException异常,如图所示:

图片

图片

使用CopyOnWriteArrayList则程序不会报错。

3.数据最终一致性

虽然CopyOnWriteArrayList读和写使用的并不是同一个array对象,不能够保证一个线程数据在写的时候另外一个线程立马能读到,但是因为使用了锁所以最终读到的数据都是一致的。

CopyOnWriteArrayList的缺点:

  1. 内存占用太大,缺点很明显的就是在wirte操作的时候,我们发现它都是使用Arrays.copyOf复制到一个新数组来完成的,如果有频繁的wirte操作就比较的占用内存,可能引起频繁的JVMYong GC和Full GC操作,write操作效率比较低;

  2. 无法保证数据的实时一致性,因为其读和写在不同的array中操作,所以如果多个线程在操作,例如线程A、B,如果想要保证线程A写入线程B马上能读到就不行,但是不适合对实时性要求比较高的场景。

CopyOnWriteArrayList使用场景:

CopyOnWriteArrayList适合使用在数据读多写少的情况下,如果数据对实时性要求比较高的业务场景则不适合使用CopyOnWriteArrayList。例如:如果业务需要配置信息、有黑名单、白名单等一些更新不频繁但是读取频繁的场景就适合使用CopyOnWriteArrayList在存储,另外很多的一些中间件之类的核心结构也是使用的CopyOnWriteArrayList比如:MQ中间件的一种kafaka的核心数据结构等。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:09:53  更:2022-04-09 18:11:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:01:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码