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

CopyOnWriteArrayList 源码解读

一、CopyOnWriteArrayList 源码解读

JUC 中,对于 ArrayList 的线程安全用法,比较推崇于使用 CopyOnWriteArrayList ,那 CopyOnWriteArrayList是怎么解决线程安全问题的呢,本文带领大家一起解读下 CopyOnWriteArrayList 的源码,主要对几个常用的函数进行讲解。

在进行 CopyOnWriteArrayList 的源码讲解之前,先看下同样实现了线程安全的 Vector ,很多文章都说不推荐使用 Vector ,其主要原因是性能太差了,那性能为什么这么差呢?可以看下 Vector addget 的源码:

在这里插入图片描述
在这里插入图片描述

Vector 的添加和读取操作都被加上了 synchronized 锁,当并发情况下,因为锁的存在相当于变成了单线程的操作,所以效率肯定低,同样这样的优点就是保证了数据的唯一性,不会读取到脏数据。

下面再看下 CopyOnWriteArrayList 是如何解决并发问题的呢。

首先看下 CopyOnWriteArrayList 的全局变量有哪些:

在这里插入图片描述

其中 lock 锁就是每次在做写操作时,锁的句柄,array 就是具体存储数据的数组,注意这里的 arrayvolatile 所修饰,因此可以在并发情况下实现数据的可见性。

new 创建了一个 CopyOnWriteArrayList 时,如果是使用无参的构造函数,则将 array 的长度默认成 0 ,创建了一个空的数组。

在这里插入图片描述
在这里插入图片描述

在使用 add 添加数据时,先使用 lock 上锁,并获取到当前的 array 数组,然后对 array 进行 copyOf,新的数组的长度是之前的长度 +1 ,这样才能存放当前新的值,将新值填充后,再替换掉旧的 array 数组后,释放当前锁。

在这里插入图片描述

在使用 get 获取指定下边数据时,直接对当前的 array 进行操作:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在进行 remove 删除时,先使用 lock 上锁,然后再获取当前的 array 数组,如果传入的 index 正好是最后一个,那么 numMoved 计算出来就是 0 ,则使用 copyOf ,长度进行 -1 去除最后一个数据。否则传入的不是最后一个,先声明一个新的 array 数组,数组的长度就是旧的 arraylen - 1,再将 0index 的数据 arraycopy 至新的 array 数组,然后再将 index + 1 后的再 arraycopy 至新的 array 数组,最后将新的 array 数组替换旧的,然后释放锁。

在这里插入图片描述

二、总结

  1. new 新建一个 CopyOnWriteArrayList 后会生成一个数组 array 来存放添加的内容,如果是无参的构造函数,则 array 的长度为 0 ,添加数据时再进行扩容。同时会声明一个 ReentrantLock 锁。
  2. 当进行 add 操作时,先进行上锁,然后对当前的 array 进行 copyOf,并且新的长度是之前的长度 +1 ,这样才能存放当前新的值,将新值填充后,再替换掉旧的 array 数组后,释放当前锁。
  3. 当使用 get 获取数据时,无需上锁,直接读取当前 array 数组的指定位置。
  4. 当使用 remove 时,同样先进行上锁,然后再获取当前的 array 数组,如果传入的 index 正好是最后一个,则使用 copyOf ,长度进行 -1 ,否则的话先声明一个新的 array 数组,现将0index 的数据 arraycopy 至新的 array 数组,然后再将 index + 1 后的再 arraycopy 至新的 array 数组,最后将新的 array 数组替换旧的,然后释放锁。

读下来之后可以感觉出来 CopyOnWriteArrayList 的源码非常容易理解和阅读,同时我们也可以看出一些问题,CopyOnWriteArrayList 实现了写写隔离,但读读是可以共享的,这就有可能出现当某个数据再修改时,读进行了操作,导致读取到的还是旧的数据。还有就是每次写操作都对数组进行 Copy ,假如数据量非常大的情况下,进行 Copy 消耗的资源则会进行 x 2 ,因此使用 CopyOnWriteArrayList 时,需要考虑下自己的数据量以及读写的频次。

相关文章:

CopyOnWriteArrayList 源码解读

一、CopyOnWriteArrayList 源码解读 在 JUC 中,对于 ArrayList 的线程安全用法,比较推崇于使用 CopyOnWriteArrayList ,那 CopyOnWriteArrayList是怎么解决线程安全问题的呢,本文带领大家一起解读下 CopyOnWriteArrayList 的源码…...

方法

方法方法(函数)一、课前问答二、方法和函数三、方法的参数3.1 单个参数3.2 多个参数四、方法的返回值五、方法的多级调用六、递归方法(函数) 一、课前问答 1、break和continue的区别 2、嵌套循环的执行流程 3、二进制有哪些运算&…...

C/C++实现发送邮件功能(附源码)

C++常用功能源码系列 本文是C/C++常用功能代码封装专栏的导航贴。部分来源于实战项目中的部分功能提炼,希望能够达到你在自己的项目中拿来就用的效果,这样更好的服务于工作实践。 专栏介绍:专栏讲本人近10年后端开发常用的案例,以高质量的代码提取出来,并对其进行了介绍。…...

Java虚拟机JVM-运行时数据区域说明

及时编译器 HotSpot虚拟机中含有两个即时编译器,分别是编译耗时短但输出代码优化程度较低的客户端编译器(简称为C1)以及编译耗时长但输出代码优化质量也更高的服务端编译器(简称为C2),通常它们会在分层编译…...

修复电子管

年前在咸鱼捡漏买到了10根1G4G电子管,这是一种直热三极管,非常的少见。买回来的时候所有的灯丝都是通的,卖家说都是新的,库存货,但是外观实在是太糟糕了,看着就像被埋在垃圾场埋了几十年的那种,…...

【Java】反射机制和代理机制

目录一、反射1. 反射概念2. 反射的应用场景3. 反射机制的优缺点4. 反射实战获取 Class 对象的四种方式二、代理机制1. 代理模式2. 静态代理3. 动态代理3.1 JDK动态代理机制1. 介绍2.JDK 动态代理类使用步骤3. 代码示例3.2 CGLIB 动态代理机制1.介绍2.CGLIB 动态代理类使用步骤3…...

synchronized底层

Monitor概念一、Java对象头二、Monitor2.1、Monitor—工作原理2.2、Monitor工作原理—字节码角度2.2、synchronized进阶原理(优化)2.3、synchronized优化原理——轻量级锁2.4、synchronized优化原理——锁膨胀2.5、synchronized优化原理——自旋优化2.6、…...

数据结构:复杂度的练习(笔记)

数据结构:复杂度的练习(笔记) 例题一: 可以先给数组排序,然后再创建一个i值,让他循环一次一次,遍历这个排序后的数组,但如果用qsort函数进行排序,时间复杂度就和题目要求…...

JAVA练习69- 从前序与中序遍历序列构造二叉树

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 提示:这里可以添加本文要记录的大概内容: 3月5日练习内容 提示:以下是本篇文章正文内容,下面案例可供参考 一、题目-从…...

brew安装问题

最近使用mac安装了Python和PyCharm,使用python中的绘制图像的turtle库后,执行报错: import _tkinter # If this fails your Python may not be configured for Tk ModuleNotFoundError: No module named _tkinter 查询后需在mac 命令行执行&…...

【数据挖掘与商务智能决策】第一章 数据分析与三重工具

numpy基础 numpy与数组 import numpy as np # 用np代替numpy,让代码更简洁 a [1, 2, 3, 4] # 创建列表a b np.array([1, 2, 3, 4]) #从列表ach print(a) print(b) print(type(a)) #打印a类型 print(type(b)) #打印b类型[1, 2, 3, 4] [1 2 3 4] <class ‘list’>…...

计算机底层:BDC码

计算机底层&#xff1a;BDC码 BDC码的作用&#xff1a; 人类喜欢十进制&#xff0c;而机器适合二进制&#xff0c;因此当机器要翻译二进制给人看时&#xff0c;就会进行二进制和十进制的转换&#xff0c;而常规的转换法&#xff08;k*位权&#xff09;太麻烦。因此就出现了不同…...

【C++】平衡二叉搜索(AVL)树的模拟实现

一、 AVL树的概念 map、multimap、set、multiset 在其文档介绍中可以发现&#xff0c;这几个容器有个共同点是&#xff1a;其底层都是按照二叉搜索树来实现的&#xff0c;但是二叉搜索树有其自身的缺陷&#xff0c;假如往树中插入的元素有序或者接近有序&#xff0c;二叉搜索树…...

[2019红帽杯]childRE

题目下载&#xff1a;下载 参考&#xff1a;re学习笔记&#xff08;24&#xff09;BUUCTF-re-[2019红帽杯]childRE_Forgo7ten的博客-CSDN博客 这道题涉及到c函数的修饰规则&#xff0c;按照规则来看应该是比较容易理解的。上面博客中有总结规则&#xff0c;可以学习一下。 载…...

2D图像处理:九点标定_下(机械手轴线与法兰轴线不重合)(附源码)

文章目录 2. 机械手轴线与法兰轴线不重合2.1 两次拍照避免标定旋转中心2.2 旋转中心标定2.3 非标定中心的方法2.3.1 预备内容-点坐标旋转计算2.3.2 工件存在平移和旋转3. 代码(待更新)上一篇:2D图像处理:九点标定_上(机械手轴线与法兰轴线重合)(附源码) 2. 机械手轴线…...

【二分查找】分巧克力、机器人跳跃、数的范围

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…...

Hyperf使用RabbitMQ消息队列

Hyperf连接使用RabbitMQ消息中间件 传送门 使用Docker部署RabbitMQ&#xff0c;->传送门<使用Docker部署Hyperf&#xff0c;->传送门-< 部署环境 安装amqp扩展 composer require hyperf/amqp安装command命令行扩展 composer require hyperf/command配置参数 假…...

【Linux】P3 用户与用户组

用户与用户组root 超级管理员设置超级管理员密码切换到超级管理员sudo 临时使用超级权限用户与用户组用户组管理用户管理getentroot 超级管理员 设置超级管理员密码 登陆后不会自动开启 root 访问权限&#xff0c;需要首先执行如下步骤设定 root 超级管理员密码 1、解除 roo…...

Spring核心模块——Aware接口

Aware接口前言基本内容例子结尾前言 Spring的依赖注入最大亮点是所有的Bean对Spring容器对存在都是没有意识到&#xff0c;Spring容器中的Bean的耦合度是很低的&#xff0c;我们可以将Spring容器很容易换成其他的容器。 但是实际开发的时候&#xff0c;我们经常要用到Spring容…...

Linux网络编程 第六天

目录 学习目标 libevent介绍 libevent的安装 libevent库的使用 libevent的使用 libevent的地基-event_base 等待事件产生-循环等待event_loop 使用libevent库的步骤&#xff1a; 事件驱动-event 编写一个基于event实现的tcp服务器&#xff1a; 自带buffer的事件-buff…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...