JAVA-CopyOnWrite并发集合

news2024/11/30 14:25:58

文章目录

    • JAVA并发集合
    • 1_实现原理
    • 2_什么是CopyOnWrite?
    • 3_CopyOnWriteArrayList的原理
    • 4_CopyOnWriteArraySet
    • 5_使用场景
    • 6_总结

JAVA并发集合

从Java5开始,Java在java.util.concurrent包下提供了大量支持高效并发访问的集合类,它们既能包装良好的访问性能,有能包装线程安全。这些集合类可以分为两部分,它们的特征如下:

  • 以Concurrent开头的集合类:
    以Concurrent开头的集合类代表了支持并发访问的集合,它们可以支持多个线程并发写入访问,
    这些写入线程的所有操作都是线程安全的,但读取操作不必锁定。以Concurrent开头的集合类
    用了更复杂的算法来保证永远不会锁住整个集合
    ,因此在并发写入时有较好的性能。
  • 以CopyOnWrite开头的集合类:
    以CopyOnWrite开头的集合类采用复制底层数组的方式来实现写操作。当线程对此类集合执行读
    取操作时,线程将会直接读取集合本身,无须加锁与阻塞。当线程对此类集合执行写入操作时,集
    合会在底层复制一份新的数组,接下来对新的数组执行写入操作。由于对集合的写入操作都是对数
    组的副本执行操作
    ,因此它是线程安全的。
  • 扩展阅读
    java.util.concurrent包下线程安全的集合类的体系结构:
    在这里插入图片描述

本文将主要讲解以CopyOnWrite开头的集合类:

1_实现原理

在Java中,CopyOnWrite系列的集合(如CopyOnWriteArrayListCopyOnWriteArraySet)是线程安全的集合类,适用于读操作频繁且写操作相对较少的场景。它们通过一种名为 “写时复制”(Copy-On-Write,简称COW)的策略来实现线程安全。

2_什么是CopyOnWrite?

概括为"写时复制",通俗的讲是写数据的时候弄出一个新的数组,然后讲旧的数据拷贝过去,更新后再将引用指向新数组。这样在添加删除元素时就不会影响旧数组的读取了,确保高并发时读的效率,但是存在延时。

下面以CopyOnWriteArrayListCopyOnWriteArraySet为例对CopyOnWrite系列的集合进一步讲解。

3_CopyOnWriteArrayList的原理

CopyOnWriteArrayList是一个线程安全的可变数组实现,内部通过复制底层数组来处理并发写操作。其主要特性是:

  • 读操作不需要锁:因为读操作不会修改数组,因此可以并发进行。
  • 写操作通过复制实现:每次写操作(如添加、删除、更新)都会创建底层数组的一个新副本,修改副本后再将其设置为新的底层数组。

内部实现机制:

以下是CopyOnWriteArrayList的核心实现机制:

  • 底层数据结构
    CopyOnWriteArrayList内部使用一个volatile修饰的数组来存储元素,确保多线程环境下对数组的可见性。

    private transient volatile Object[] array;
    
  • 读操作

    读操作直接访问底层数组,无需加锁。

    public E get(int index) {
    	return get(array, index);
    }
    
    final Object[] getArray() {
    	return array;
    }
    
    private E get(Object[] a, int index) {
    	return (E) a[index];
    }
    
  • 写操作

    写操作在进行修改时,会首先复制底层数组,然后在新数组上进行修改,最后将新数组设置为底层数组。

    public boolean add(E e) {
    	final ReentrantLock lock = this.lock;
    	lock.lock();
    	try {
        	Object[] elements = getArray();       // 获取当前数组
        	int len = elements.length;            // 获取当前数组的长度
        	Object[] newElements = Arrays.copyOf(elements, len + 1); // 复制数组,并增加一个位置
        	newElements[len] = e;                 // 将新元素添加到新数组的最后一个位置
        	setArray(newElements);                // 用新数组替换旧数组
        	return true;
    	} finally {
        	lock.unlock();                        // 释放锁
    	}
    }
    
    
    final void setArray(Object[] a) {
    	array = a;
    }
    

在这个示例中,add方法首先获取锁以确保写操作的线程安全。然后,它复制现有的数组,增加一个新元素,并将新数组设置为底层数组。

添加操作会复制新的数组并将原元素长度加一,那么移除一个元素呢?

  • 移除操作:
    public boolean remove(Object o) {
    	final ReentrantLock lock = this.lock;
    	lock.lock();
    	try {
        	Object[] elements = getArray();
        	int len = elements.length;
    
        	// 寻找要移除的元素的位置
        	int i = 0;
        	for (; i < len; i++) {
            	if (o.equals(elements[i])) {
                	break;
            	}
        	}
    
        	// 如果没有找到元素,直接返回false
        	if (i == len) {
            	return false;
        	}
    
        	// 创建新数组,长度比当前数组少一个
        	Object[] newElements = new Object[len - 1];
        
        	// 复制前面的元素
        	System.arraycopy(elements, 0, newElements, 0, i);
        
        	// 复制后面的元素
        	System.arraycopy(elements, i + 1, newElements, i, len - i - 1);
        
        	// 设置新数组
        	setArray(newElements);
        	return true;
    	} finally {
        	lock.unlock();
    	}
    }
    
    

CopyOnWriteArrayList中,移除元素的操作也是通过复制数组并在新数组上进行操作来实现的。虽然每次移除操作都会创建一个新数组,存在一定的性能开销,但这种设计能够确保线程安全,适合读多写少的场景。

既然remove、add已经了解了,那么 set 也就不难猜测了,public E set(int index, E element)操作时也是拷贝原数组然后进行操作,只不过长度相对原数组既没有增加也没有减少。

4_CopyOnWriteArraySet

CopyOnWriteArraySet是基于CopyOnWriteArrayList实现的线程安全的集合。它利用CopyOnWriteArrayList来存储元素,并确保集合中的元素不重复。

5_使用场景

CopyOnWrite集合适用于以下场景:

  1. 读多写少:由于每次写操作都会复制整个数组,因此写操作的开销较大。适用于读操作频繁、写操作较少的场景。
  2. 遍历操作:在遍历过程中,不会受到并发修改的影响,因为任何写操作都会创建一个新的数组副本,不会修改正在遍历的数组。

优缺点

优点

  • 线程安全:通过写时复制机制实现线程安全,读操作无锁,性能高。
  • 适用于读多写少的场景:在读操作远多于写操作的情况下,性能表现优秀。
  • 不需要手动同步:用户无需手动添加同步代码,简化了并发编程。

缺点

  • 内存开销大:每次写操作都会创建数组副本,占用额外的内存。
  • 写操作性能差:写操作需要复制数组,性能较低。

示例代码

以下是CopyOnWriteArrayList的简单示例代码:

import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteExample {
    public static void main(String[] args) {
        CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();

        // 添加元素
        list.add(1);
        list.add(2);
        list.add(3);

        // 读取元素
        System.out.println("Element at index 0: " + list.get(0));

        // 遍历元素
        for (Integer element : list) {
            System.out.println("Element: " + element);
        }

        // 删除元素
        list.remove(Integer.valueOf(2));
        System.out.println("After removal: " + list);
    }
}

6_总结

CopyOnWrite系列集合通过写时复制机制实现线程安全,适用于读操作频繁且写操作较少的场景。虽然写操作的开销较大,但在读操作占多数的应用中,CopyOnWrite集合可以提供高效且线程安全的性能。

CopyOnWriteArrayList中,移除元素的操作与添加元素类似,通过复制数组并在新数组上进行操作来实现线程安全。移除元素时,需要创建一个新的数组,长度比当前数组少一个,然后复制所有不需要移除的元素到新数组中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1824572.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SwiGLU激活函数与GLU门控线性单元原理解析

前言 SwiGLU激活函数在PaLM&#xff0c;LLaMA等大模型中有广泛应用&#xff0c;在大部分测评中相较于Transformer FFN中所使用的ReLU函数都有提升。本篇先介绍LLaMA中SwiGLU的实现形式&#xff0c;再追溯到GLU门控线性单元&#xff0c;以及介绍GLU的变种&#xff0c;Swish激活…

phpcms仿蚁乐购淘宝客网站模板

phpcms仿蚁乐购网站模板&#xff0c;淘宝客行业模板免费下载&#xff0c;该模板网站很容易吸引访客点击&#xff0c;提升ip流量和pv是非常有利的。本套模板采用现在非常流行的全屏自适应布局设计&#xff0c;且栏目列表以简洁&#xff0c;非常时尚大气。页面根据分辨率大小而自…

华为北向网管NCE开发教程(7)历史告警采集

1准备工作 准备一个FTP服务器和网管北向网络通&#xff0c;网管北向生成告警文件&#xff0c;会推送到准备的FTP服务器上。 linux&#xff0c;都是自带FTP的&#xff0c;如果是linux则无需自己搭建&#xff0c;如果是windows则需要自己搭建 2生成告警文件 2.1方法说明getAll…

使用libcurl实现简单的HTTP访问

代码; #include <stdio.h> #include <stdlib.h> #include <curl/curl.h> // 包含libcurl库 FILE *fp; // 定义一个文件标识符 size_t write_data(void *ptr,size_t size,size_t nmemb,void *stream) { // 定义回调函数&#xff0c;用于将…

LeetCode-2779. 数组的最大美丽值【数组 二分查找 排序 滑动窗口】

LeetCode-2779. 数组的最大美丽值【数组 二分查找 排序 滑动窗口】 题目描述&#xff1a;解题思路一&#xff1a;滑动窗口与排序解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个下标从 0 开始的整数数组 nums 和一个 非负 整数 k 。 在一步操…

《华为项目管理之道》第1章笔记

《华为项目管理之道》&#xff0c;是新出的华为官方的项目管理书&#xff0c;整个书不错。第1章的精华&#xff1a; 1.2.2 以项目为中心的机制 伴随着项目型组织的建立&#xff0c;华为逐步形成了完备的项目管理流程和制度&#xff0c;从而将业务运 作构建在项目经营管理之…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 启动多任务排序(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 启动多任务排序(200分) 🌍 评测功能需要订阅专栏后私信联系…

STM32HAL-最简单的时间片论法

目录 概述 一、开发环境 二、STM32CubeMx配置 三、编码 四、运行结果 五、总结 概述 本文章使用最简单的写法时间片论法框架,非常适合移植各类型单片机,特别是资源少的芯片上。接下来将在stm32单片机上实现,只需占用1个定时器作为tick即可。(按键框架+时间片论法)…

cs61C | lecture4

cs61C | lecture4 C 语言内存布局 ### Stack 在最顶部&#xff0c;向下增长。包含局部变量和 function frame information。 > Each stack frame is a contiguous block of memory holding the local variables of a single procedure. > A stack frame includes: > …

Leaflet集成wheelnav在WebGIS中的应用

目录 前言 一、两种错误的实现方式 1、组件不展示 2、意外中的空白 二、不同样式的集成 1、在leaflet中集成wheelnav 2、给marker绑定默认组件 2、面对象绑定组件 3、如何自定义样式 三、总结 前言 在之前的博客中&#xff0c;我们曾经介绍了使用wheelnav.js构建酷炫…

简易开发一个app

即时设计网站 即时设计 - 可实时协作的专业 UI 设计工具 需要先设计好UI界面 上传到codefun 首次需要安装 自动生成代码 打开hb软件 新建项目 打开创建的项目 删除代码 复制代码过去 下载图片 将图片放到文件夹里 改为这种格式 index.vue 如果不需要uni-app导航栏可以修改 …

Vue43-单文件组件

一、脚手架的作用 单文件组件&#xff1a;xxx.vue&#xff0c;浏览器不能直接运行&#xff01;&#xff01;&#xff01; 脚手架去调用webpack等第三方工具。 二、vue文件的命名规则 建议用下面的两种方式。&#xff08;首字母大写&#xff01;&#xff01;&#xff01;&#x…

云原生系列之Docker常用命令

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 系列文章目录 云原生之…

大模型算法备案全网最详细说明(附附件)

本文要点&#xff1a;大模型备案最详细说明&#xff0c;大模型备案条件有哪些&#xff0c;《算法安全自评估报告》模板&#xff0c;大模型算法备案&#xff0c;大模型上线备案&#xff0c;生成式人工智能(大语言模型)安全评估要点&#xff0c;网信办大模型备案。 共分为以下几…

逻辑这回事(五)---- 资源优化

基础篇 Memory 避免细碎的RAM。将大的RAM拆分成多个小RAM&#xff0c;并根据地址关断可以优化功耗&#xff0c;但把多个小RAM合成大RAM可以优化面积。Block RAM和分布式RAM合理选择。根据存储容量&#xff0c;对Block RAM和分布式RAM的实现面积和功耗进行评估&#xff0c;选择…

「网络原理」IP 协议

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;计网 &#x1f387;欢迎点赞收藏加关注哦&#xff01; IP 协议 &#x1f349;报头结构&#x1f349;地址管理&#x1f34c;动态分配 IP 地址&#x1f34c;NAT 机制&#xff08;网络地址映射&am…

【计算机毕业设计】242基于微信小程序的外卖点餐系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

SX2106B 2A同步降压型DC/DC转换器芯片IC

一般描述 SX2106B是一款同步降压DC/DC转换器&#xff0c;提供宽广的4.5V至24V输入电压范围和2A连续负载电流能力。 SX2106B故障保护包括逐周期电流限制、UVLO、输出过电压保护和热关机。可调软启动功能&#xff0c;防止启动时的浪涌电流。该器件采用电流模式控…

四轴飞行器、无人机(STM32、NRF24L01)

一、简介 此电路由STM32为主控芯片&#xff0c;NRF24L01、MPU6050为辅,当接受到信号时&#xff0c;处理对应的指令。 二、实物图 三、部分代码 void FlightPidControl(float dt) { volatile static uint8_t statusWAITING_1; switch(status) { case WAITING_1: //等待解锁 if…

Syncovery:跨平台高效文件备份与同步的得力助手

在数字化时代&#xff0c;数据安全与文件同步已成为个人及企业不可或缺的需求。Syncovery作为一款专为Mac和Windows用户设计的文件备份和同步工具&#xff0c;凭借其高效、安全和易用的特点&#xff0c;赢得了广泛赞誉。 一、强大备份功能 Syncovery支持多种备份方案和数据格…