JAVA-CopyOnWrite并发集合

文章目录

    • 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.mfbz.cn/a/710373.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【字符函数】

接下来介绍部分字符函数测试 2. 字符转换函数 1.字符分类函数 1.1iscntrl 注&#xff1a;任何控制字符 检查是否有控制字符 符合为真 int main() {int i 0;char str[] "first line \n second line \n";//判断是否遇到控制字符while (!iscntrl(str[i])){p…

springboot网上书店管理系统-计算机毕业设计源码03780

摘 要 网上书店管理系统采用B/S结构、java开发语言、以及Mysql数据库等技术。系统主要分为管理员和用户两部分&#xff0c;管理员管理主要功能包括&#xff1a;首页、站点管理&#xff08;轮播图&#xff09;用户管理&#xff08;管理员、注册用户&#xff09;内容管理&#x…

51单片机STC89C52RC——代码编译

1&#xff0c;勾选 “Create HEX file” 2&#xff0c;编译

【智源大会2024】(一)智源技术专题

智源的全家桶&#xff1a; 微调数据相关&#xff1a; 1.千万级数据集: BAAI创建了首个千万级别的高质量开源指令微调数据集。 2.模型性能与数据质量: 强调了模型性能与数据质量之间的高度相关性。 3.技术亮点: 使用了高质量的指令数据筛选与合成技术。这些技术显著提升了模型…

效率翻倍!ComfyUI 必装的工作流+模型管理插件 Workspace Manager

一、Workspace Manager 安装方式 插件 Github 网址&#xff1a; https://github.com/11cafe/comfyui-workspace-manager 如果你没有安装 Workspace Manager 插件&#xff0c;可以通过以下 2 种方式安装&#xff1a; ① 通过 ComfyUI Manager 安装&#xff08;推荐&#xff0…

AI办公自动化:kimi批量搜索提取PDF文档中特定文本内容

工作任务&#xff1a;PDF文档中有资料来源这一行&#xff0c;比如&#xff1a; 资料来源&#xff1a;moomoo tech、The Information、Bloomberg、Reuters&#xff0c;浙商证券研究所 数据来源&#xff1a;CSDN、浙商证券研究所 数据来源&#xff1a;CSDN、arXiv、浙商证券研…

OpenGL3.3_C++_Windows(7)

演示 最终演示效果 ​​​​ 冯氏光照 光照原理&#xff1a;对于向量相乘默认为点乘&#xff0c;如果*lightColor(1.0f, 1.0f, 1.0f);白光&#xff0c;值不变物体的颜色显示原理&#xff1a;不被物体吸收的光反射&#xff0c;也就是由白光分解后的一部分&#xff0c;因此&…

力扣 面试题17.04.消失的数字

数组nums包含从0到n的所有整数&#xff0c;但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗&#xff1f; 示例 1&#xff1a; 输入&#xff1a;[3,0,1] 输出&#xff1a;2 示例 2&#xff1a; 输入&#xff1a;[9,6,4,2,3,5,7,0,1] 输出&#x…

JavaScript 规范霍夫曼编码

霍夫曼编码是一种无损数据压缩算法&#xff0c;其中数据中的每个字符都分配有可变长度的前缀代码。出现频率最低的字符获得最大代码&#xff0c;出现频率最高的字符获得最小代码。使用这种技术对数据进行编码非常简单且高效。但是&#xff0c;解码使用此技术生成的比特流效率低…

自然语言处理:第三十五章Embedding 测评榜单MTEB

文章链接: [2210.07316] MTEB: Massive Text Embedding Benchmark (arxiv.org) 项目地址: mteb:MTEB: Massive Text Embedding Benchmark - GitCode github地址: FlagEmbedding/C_MTEB at master FlagOpen/FlagEmbedding (github.com) Hugging Face Leadboard: MTEB Leader…

『SD』ControlNet基础讲解

本文简介 在学习和使用『Stable Diffusion』的过程中&#xff0c;『ControlNet』是一个不可忽视的关键组件。『ControlNet』是一个用于增强图像生成过程可控性的强大工具&#xff0c;允许用户通过提供特定的控制图像来精确指导生成结果。本文将讲解 『ControlNet』的基本概念。…

PHP杂货铺家庭在线记账理财管理系统源码

家庭在线记帐理财系统&#xff0c;让你对自己的开支了如指掌&#xff0c;图形化界面操作更简单&#xff0c;非常适合家庭理财、记账&#xff0c;系统界面简洁优美&#xff0c;操作直观简单&#xff0c;非常容易上手。 安装说明&#xff1a; 1、上传到网站根目录 2、用phpMyad…

目前市面上DIY高端空心耳机壳使用的透明原材料是什么?

目前市面上DIY高端空心耳机壳使用的透明原材料是什么&#xff1f; DIY制作耳机壳的UV树脂胶是一种单组份、通过紫外线光固化的胶粘剂&#xff0c;具有低能量固化、收缩低、发热量低、高透明、耐盐酸、耐黄变好、高硬度、韧性好、成型好等特点。这种胶粘剂非常适合用于制作耳机壳…

python-基础篇-文件和异常

文章目录 文件和异常读写文本文件读写二进制文件读写JSON文件 文件和异常 实际开发中常常会遇到对数据进行持久化操作的场景&#xff0c;而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词&#xff0c;可能需要先科普一下关于文件系统的知识&#…

Chromium源码阅读:从页面加载到元素展示(1)

​ 从&#xff1c;p&#xff1e;hello world&#xff1c;/p&#xff1e;.html到界面上的hello world 今天&#xff0c;我们一起来看看一个html元素&#xff0c;是如何绘制到界面上。我们选择了最简单的场景&#xff0c;便于快速掌握总体的流程&#xff0c;加深之前阅读知识的…

深入理解并打败C语言难关之一————指针(4)

前言&#xff1a; 我们在前面的几讲中已经讲了指针的很多内容了&#xff0c;现在我们开始层层递进&#xff0c;要探寻更多的指针喽&#xff0c;不多废话了&#xff0c;直接进入正题&#xff0c;开始今天的指针之旅喽&#xff01; 目录&#xff1a; 1.字符指针变量 1.1常量字符…

除了程序员,你又是谁呢?别说!保护自己能量最好的方式——早读(逆天打工人爬取热门微信文章解读)

你很困的时候&#xff0c;会不会遵循本心直接睡觉呢&#xff1f; 引言Python 代码第一篇 洞见 保护自己能量最好的方式第二篇 视频新闻结尾 引言 现在真的是越来越遵循本心了 昨天晚上10点多 觉得好困 但是又没有洗澡 然后就想着算了 躺一个 没想到一躺 早上6点了 起来速速洗刷…

2024年心理学研究、现代化教育与社会发展国际学术会议(PRMESD 2024)

2024年心理学研究、现代化教育与社会发展国际学术会议(PRMESD 2024) 2024 International Conference on Psychological Research, Modern Education and Social Development 会议地点&#xff1a;南京&#xff0c;中国 网址&#xff1a;www.prmesd.com 邮箱: prmesdsub-con…

浔川计算机v1.1——浔川python科技社

浔川计算机v1.1 import tkinter import math import tkinter.messageboxclass Calculator(object):# 界面布局方法def __init__(self):# 创建主界面,并且保存到成员属性中self.root tkinter.Tk()self.root.minsize(280, 450)self.root.maxsize(280, 470)self.root.title(浔川计…

LabVIEW 32位与64位版本比较分析:性能与兼容性详解

LabVIEW的32位和64位版本在功能、性能、兼容性和应用场景等方面存在差异。本文从系统要求、内存管理、性能、兼容性、驱动支持和开发维护等多个角度进行详细分析&#xff0c;帮助用户选择合适的版本。 一、系统要求 操作系统支持&#xff1a; 32位LabVIEW&#xff1a;可以在32位…