(6)并发编程高级篇-CopyOnWriteArrayList

CopyOnWriteArrayList与vector的爱恨情仇 CopyOnWriteArrayList 1. 与vector以及Collections.synchronizedList()实现原理上的区别 1、vector是通过在每个方法加synchronized实现,包括最简单的size()方法     public synchronized int size() {        return e 阅读详情
介绍

java并发包中的并发List只有CopyOnWriteArrayList,CopyOnWriteArrayList的修改操作底层都是通过拷贝一份数组进行的。使用ReentrantLock独占锁来保证多线程并发下只有一个线程进行修改操作,下面我们通过源码分析来逐步了解。

初始化方法
   /**
     * Creates an empty list.
     */
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }

无参构造器中,创建了一个长度为1Object数组.

添加元素

在这里插入图片描述
从上图可知CopyOnWriteArrayList的添加元素方法有7个,我们着重讲下add(E) 这个方法,其他方法的实现原理大同小异。


    /**
     * Appends the specified element to the end of this list.
     * 翻译:在列表的最后添加元素
     * @param e element to be appended to this list
     * 翻译:添加到列表的元素
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
         //1. 获取重入锁(独占锁)
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
        //2. 获取array
            Object[] elements = getArray();
            int len = elements.length;
            //3. 复制原array到新array,并添加元素
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            //4. 将新array替换原array
            setArray(newElements);
            return true;
        } finally {
           //5. 释放重入锁
            lock.unlock();
        }
    }

从1 和 5 可以看出 的方法,通过独占锁的机制,保证多线程并发修改元素时,只能有一个线程进行,其他线程会阻塞挂起,从而确保了此方法的原子性。
2 、3 处 通过复制原array到新array中,通过对新array进行添加元素操作,此处可知CopyOnWriteArrayList是一个无界的队列。4 处 将 新数组替换了原数组

删除元素

在这里插入图片描述
CopyOnWriteArrayList 有6个删除方法,我们着重讲解下remove(int)这个方法。

  /**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left 
     *   Returns the element that was removed from the list.
     * 翻译:删除列表中指定位置的元素,往左边移动随后的元素,返回从列表中删除的元素。
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E remove(int index) {
    //1. 获取锁
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
        //2. 获取原array
            Object[] elements = getArray();
            //3. 获取要删除的元素
            int len = elements.length;
            E oldValue = get(elements, index);
            int numMoved = len - index - 1;

            if (numMoved == 0)
                setArray(Arrays.copyOf(elements, len - 1));
            else {
            //4. 通过两次复制,来删除元素并整合新的array
                Object[] newElements = new Object[len - 1];
                System.arraycopy(elements, 0, newElements, 0, index);
                System.arraycopy(elements, index + 1, newElements, index,
                                 numMoved);
              //5. 新array替换原array
                setArray(newElements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }
获取指定位置元素
    @SuppressWarnings("unchecked")
    private E get(Object[] a, int index) {
        return (E) a[index];
    }

    /**
     * {@inheritDoc}
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        return get(getArray(), index);
    }

在如上代码中,当线程threadA 执行get(int index ),是分两个步骤:1. 获取数组 2. 通过数组下标index索引获取指定元素,它会存在数据弱一致性的问题。当线程threadB 在 线程 threadA执行步骤1后和步骤2之前时,删除了threadA 要访问的元素(假设为x元素),那么threadA执行步骤2时获取的是x元素,而不是其他的。因为threadA在执行步骤1后,操作的是原数组(局部变量)。

总结

CopyOnWriteArrayList通过写时复制来保证数据的一致性,而它获取、修改、写入这三个操作并不是原子性,所以通过独占锁来保证任何一时刻只能有一个线程对数据进行操作。另外CopyOnWriteArraySet的实现原理和CopyOnWriteArrayList也是类似的。

并发编程高级篇 目录 线程安全 synchronized&volatile 同步类容器、并发类容器"Concurrent"、“CopyOnWrite” Queue 生产者消费者模式 Executors线程池 JMS规范 ActiveMQAPI讲解 ActiveMQ高级主题(点对点模式/发布与订阅模式) 多线程+ActiveMQ负载均衡实战 并发编程学习目的 线程安全 多个线程多个锁 对象锁的同步和异步 同步:synchronized 异步:asynchronized 示例代码 示例总结 脏读 示例代码 示例总结 阅读详情

相关推荐

基于深度学习的中文方言识别模型训练实战

本文介绍了一个基于深度学习的中文方言识别模型开发流程。项目采用PyTorch框架和Chinese-BERT-wwm预训练模型,构建了包含BERT基础层、方言特征增强层和注意力机制的多方言分类系统。文中详细阐述了数据收集策略,包括从社交媒体、语料库和众包平台获取多源数据,并实现了文本清洗、同义词替换和回译等数据增强技术。模型架构部分展示了如何在BERT基础上添加方言特征提取层和多头注意力机制来提升识别性能。该方案支持普通话、粤语等6种主要方言的识别,目标准确率达90%以上,响应时间小于100ms,适用于智能客

电脑管家 1730

CopyOnWriteArrayList解析

CopyOnWriteArrayList是ArrayList 的一个线程安全的变体,其中所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的。 其原理是: 初始化的时候只有一个容器,很长一段时间,这个容器数据、数量等没有发生变化,多个线程都是读取同一个容器中的数据,所以这样大家读到的数据都是唯一、一致、安全的,如果后来有线程往里面增加了一个数据,这个时候Copy

TuGeLe的博客 593

RoboMaster机甲大师赛备赛:如何用STM32+CAN总线精准控制四个大疆3508电机?

本文详细介绍了在RoboMaster机甲大师赛中,如何利用STM32和CAN总线技术精准控制四台大疆3508电机。从硬件架构设计、多电机ID分配、数据解析到同步控制算法,全面解析了构建高响应、低延迟底盘驱动系统的关键技术,助力参赛队伍提升机器人运动性能。

weixin_28684825的博客 134

CopyOnWriteArrayList 你了解多少?

相信大家对 ConcurrentHashMap 这个线程安全类非常熟悉,但是如果我想在多线程环境下使用 ArrayList,该怎么处理呢?阿粉今天来给你揭晓答案! 一、摘要 在介绍 CopyOnWriteArrayList 之前,我们一起先来看看如下方法执行结果,代码内容如下: public static void main(String[] args) { List<String&...

Android 开发架构 385

数字设计实验:自动售货机

本文旨在介绍数字设计实验:自动售货机的设计思路和实现代码

2401_83740084的博客 2227

手把手教你校准垂起固定翼(VTOL)遥控器与电调:从零到飞的完整流程

本文详细介绍了垂起固定翼(VTOL)遥控器与电调的校准流程,从基础认知到飞行前检查,涵盖遥控器通道配置、电调校准、舵机方向调整等关键步骤。通过图文并茂的指导,帮助无人机爱好者安全完成VTOL调试,确保首飞成功。特别强调多旋翼模式、过渡模式和固定翼模式的设置要点,适合新手和进阶用户参考。

jenkins8butler的博客 357

Java并发编程精讲

课程会讲解Java中并发相关技术的基础、原理和应用,从线程安全、线程(池),锁实现和并发容器等高并发Java实现,去深入理解在并发编程中,一些最容易被忽视的点,这些点也是我在多年编程经验中实际用到,对于每个小节小课均会有实际的场景应用为你呈现。同时这些也是面试过程中面试官考察的重点,掌握这些点,面试和工作时,做到心中有货,不慌不乱,能够胜任。

Mediapipe姿态估计——用坐标计算手指关节弯曲角度并实时标注

利用mediapipe搭建姿态检测模型;mediapipe人体标注节点坐标;mediapipe计算手指弯曲角度并实时渲染;mediapipe计算关节弯曲角度。mediapipe手势识别;mediapipe姿态检测模型;mediapipe学习。

kalakalabala的博客 1万+

Java并发编程:并发容器之CopyOnWriteArrayList(转载)

Java并发编程:并发容器之CopyOnWriteArrayList(转载)   原文链接:   http://ifeve.com/java-copy-on-write/      Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改...

weixin_38170468的博客 726

在ROS中使用行为树

在ROS中使用行为树 我提供的工程示例文件: demo链接 文章目录在ROS中使用行为树0、 学习本教程的前提1、 behaviorTree 库安装(ROS使用下的安装方式)2、 处理 behaviortree 库并准备好 service 和 ros action2.1 对ROS 的 service 和 action 进行封装,使其在 behaviortree 上使用更加方便。2.2 创建一个 service 和一个 action2.3 创建与决策树相关的数据类型2.4 修改`package.xml`文件2

qq_37416258的博客 6376

【八股】JUC并发编程篇

👉抽象队列同步器,就是一种锁,内部维护的是一个先进先出的双向队列,队列中存储的是排队的线程,用state来标识是否有线程获得锁【0是无锁状态】👉流程:当一个线程拿到锁后会修改state = 1,这时如果有其他线程访问则会进入队列进行排序,直到state变成0后,队头线程才会拿到锁。在对state进行修改时,用的是CAS操作,所以可以保证原子性。👉它可以实现公平锁或非公平锁【默认】,上述是一个公平锁。如果新线程和队头线程抢锁资源就是非公平锁。

qq_44768318的博客 552

并发编程:CopyOnWriteArrayList

并发编程:CopyOnWriteArrayList

weixin_46619605的博客 799

GEE:基于 Landsat 数据集生成(1986-2024)月度合成地表温度(LST)时间序列数据

优快云@_养乐多_本文将介绍使用 Landsat 时间序列计算(1986-2024)月度合成地表温度(LST)时间序列数据集的代码。

养乐多的博客 1713

深度解析 CopyOnWriteArrayList:并发编程中的读写分离利器

深度解析 CopyOnWriteArrayList:并发编程中的读写分离利器!🎉

qq_56158663的博客 1197

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

深入剖析Java并发编程核心原理:从ConcurrentHashMap到CopyOnWriteArrayList

在多核处理器成为主流的今天,并发编程已成为提升系统性能的关键手段。竞态条件内存可见性问题以及指令重排序带来的不确定性。这些问题直接催生了Java内存模型(JMM)的诞生,通过happens-before规则、volatile语义和同步机制构建起线程安全的基础框架。以经典的i++操作为例,这个看似简单的语句实际上包含读取、计算、写入三个步骤,在多线程环境下可能因线程切换导致计算结果丢失。传统的关键字虽然能解决这些问题,但粗粒度的锁机制往往成为性能瓶颈。此时,并发容器。

zuiyuelong的博客 707

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

【并发编程】CopyOnWriteArrayList详解与原理

本文讲解什么是CopyOnWriteArrayList以及他的特点、适用场景、缺点,CopyOnWriteArrayList的数据结构、add()、get() 方法、remove()方法的实现原理。

小明的Java问道之路 5071

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

高级并发编程系列十七(一文搞懂CopyOnWriteArrayList)

对于这个结果,你是不是感到多少有点意外!感觉与ArrayList不是一个套路对吧。

2401_89221867的博客 649

Java并发编程—CopyOnWriteArrayList

1 概述 JUC并发包中只提供了一个并发list就是CopyOnWriteList,是线程安全的(内部有一个独占锁ReetrantLock),采用的是写时复制的策略。整体的类图结构如下图所示。 下面从构造方法,增删改查与迭代器遍历来对该类进行一些详细的介绍。 2 构造方法 该类共有三个构造方法,一个无参构造,一个传入一个集合的有参构造,一个是传入一个泛型数组的有参构造 public CopyOnWriteArrayList() //无参构造器在内部创建了一个大小为0的Object数组 p..

wait2023的博客 509

【并发编程篇】解决线程安全问题 — CopyOnWriteArrayList

需要注意的是,虽然 Collections.synchronizedList() 方法可以确保对集合的基本操作是线程安全的,但在进行复合操作时仍然需要额外的同步措施。在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。此外,如果只是在单线程环境下使用集合,或者可以保证对集合的访问是单线程的,那么不一定需要使用线程安全的集合类。在刚才的案例中,我们看到,并发下,ArrayList是不安全的,下面将提供两种解决方法。

小吉妙妙屋 1525

Java并发编程之CopyOnWriteArrayList

什么是CopyOnWrite Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。 什么是CopyOnWrite容器 CopyOnWrite容器即写时复制的容器。当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容...

Geffin的博客 409

并发系列——JUC高级篇(三)List之 CopyOnWriteArrayList

并发包中的并发 List 只有 CopyOnWriteArray List。 CopyOnWri teArray List 是一个线程 安全的 ArrayList,对其进行的修改操作都是在底层的一个复制的数组(快照)上进行的, 也就是使用了写时复制策略(add/set/remove(修改)时复制新数组进行操作)。 原理:采用每add一个元素则复制出一个新数组,此时如果多线程下,add/set/...

qq_35599414的博客 889

Java并发编程:CopyOnWriteArrayList与Collections.synchronizedList深度对比

Java并发编程:CopyOnWriteArrayList与Collections.synchronizedList深度对比

嗨,欢迎来到我的 优快云 博客小天地!一名深耕多年的技术发烧友。在这里,我将把日常工作中积累的宝贵经验,从复杂架构设计的精妙之处,到代码优化的实战技巧,毫无保留地分享给大家。 5823

Java并发编程之CopyOnWriteArraylist

Java并发编程之CopyOnWriteArraylist 引言: Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非

zdl_csdn的博客 280

JAVA并发编程高级-线程安全集合-CopyOnWriteArrayList

并发包中的并发 List 只有 CopyOnWriteArrayList。CopyOnWriteArrayList是一个线程安全的 ArrayList,对其进行的修改操作都是在底层的一个复制的数组(快照)上进行的,也就是使用了写时复制策略。Copy On WriteArraylist 的类图结构如图 5-1所示。

weixin_45826852的博客 868

Java集合篇之CopyOnWriteArrayList解析与源码解读

是List接口的一个线程安全实现类,它基于动态数组实现,允许存储重复元素和null值。与Vector和不同,在读操作时不加锁,而在写操作时通过复制整个数组来实现线程安全。作为Java并发包中的一个线程安全的List实现类,采用“写时复制”策略,适用于读多写少的场景。通过源码解析,我们可以更好地理解的写时复制机制、添加和删除元素的实现细节,以及其线程安全的特性。然而,它也存在一些潜在的性能问题,如内存占用增加、写操作性能下降以及频繁的垃圾回收。因此,在使用时,需要根据具体的使用场景进行权衡和选择。

庄子兄弟的博客 1171

ArrayList和CopyOnWriteArrayList

1.ArrayList查询快而增删慢 1、底层是数组,初始化大小为10 2、插入时会判断数组容量是否足够,不够的化会进行扩容 3、所谓扩容就是新建一个数组,然后将老的数据里面的元素复制到新的数组里面 4、移除元素的时候也涉及到数组中元素的移动,删除指定index位置的元素,然后将index+1至数组最后一个元素往前移动一格 结论: ArrayList底层是数组,所以查询的时候直接根据索引可以很快地找到对应地元素,改也是如此,找到index对应元素进行替换。而增加和删除就涉及到数组元素地移动,所以会比较

mhbsoft的博客 977
上一篇: (5)并发编程高级篇-AtomicLong、LongAdder、LongAccumlator
下一篇: LockSupport工具类-入门级
yi博说
博客等级 码龄11年 20粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值