锁 和 CopyOnWrite的实现

从 0 到 1:用 Trae 插件 Builder 模式开发端午包粽子小游戏 Trae插件的Builder模式为开发者提供了一种高效的项目搭建方式,通过自然语言描述需求,能够快速生成项目框架和核心代码,减少重复性工作。本文以开发端午包粽子小游戏为例,展示了Trae插件的安装、使用及功能特点。通过自然语言描述,插件能够理解并生成项目结构、代码文件,并提供开发路线图建议。在实际开发中,虽然自然语言描述的精准度对生成结果有影响,但Trae插件在代码生成效率和项目搭建速度上表现出色,尤其适合中小项目和特定类型应用的快速开发。未来,插件在复杂大型项目的高度定制化开发方面仍有提升空间。 阅读详情

锁 和 CopyOnWrite的实现

1.普通锁

只有lock功能, Java实现:ReentrantLock lock = new ReentrantLock();

  • lock和unlock:
lock.lock();
lock.unlock();

2.读写锁

读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥。

总之,读的时候上读锁,写的时候上写锁! Java里面的实现:ReentrantReadWriteLock

ReadWriteLock mylock = new ReentrantReadWriteLock(false);
  • 读锁lock、unlock:
myLock.readLock().lock();
myLock.readLock().unlock();
  • 写锁lock、unlock:
myLock.writeLock().lock();
myLock.writeLock().unlock();

3.总结

读写锁的本意是分别对读写状态进行互斥区分,有互斥时才加锁,否则放行.

互斥的情况有:

  1. 读写互斥.
  2. 写写互斥.

不互斥的情况是:读读,

读写锁使用更加高效,尤其适用于读线程多于写线程的场景。

4.CopyOnWrite

  • 使用场景:并发少量的写,多个读(确实适合Kafka的应用场景)。
  • JDK源码有CopyOnWriteArrayList和 CopyOnWriteArraySet的实现
  • Kafka的CopyOnWriteMap是自己实现的,基于lock的;另外还有基于CAS实现的,比如com.sun.jersey.client.impl.CopyOnWriteHashMap,具体实现暂且不讨论。

CopyOnWriteArrayList的核心思想是利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值给旧的引用,并通过volatile 保证其可见性,当然写操作的锁是必不可少的了。

Kafka-0.10的队列RecordAccumulator使用了自实现的CopyOnWriteMap.关键点如下:

  • map声明: volatile
  • read操作不加锁
  • put操作加锁:synchronized

A simple read-optimized map implementation that synchronizes only writes and does a full copy on each modification

private volatile Map<K, V> map; // volatile
this.map = Collections.unmodifiableMap(map); // 不可变map

public V get(Object k) { // read操作不加锁
        return map.get(k);
    }
    
// put操作加锁,先复制,在put.
public synchronized V put(K k, V v) {
        Map<K, V> copy = new HashMap<K, V>(this.map);
        V prev = copy.put(k, v);
        this.map = Collections.unmodifiableMap(copy);
        return prev;
    }

5. CopyOnWriteArrayList - 写时复制

JDK里的CopyOnWriteArrayList,核心是任何时候,保障只有一个写者。因此,也是对读不加锁、对写进行加锁。

基本思路是,从共享同一个内容,当想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。

  • 底层实现是数组Object[],声明:volatile
  • 加锁的方式是ReentrantLock
  • copy的方法是Arrays.copyOf

5.1 add 加锁

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();
        }
    }

5.2 读不加锁

读的时候不需要加锁,如果读的时候有多个线程正在向 CopyOnWriteArrayList添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的 CopyOnWriteArrayList。

public E get(int index) {
        return get(getArray(), index);
    }

很简单,只要了解了CopyOnWrite机制,我们可以实现各种CopyOnWrite容器,并且在不同的应用场景中使用。

5.3 CopyOnWrite的应用场景

CopyOnWrite并发容器用于读多写少的并发场景。比如白名单,黑名单,商品类目的访问和更新场景,假如我们有一个搜索网站,用户在这个网站的搜索框中,输入关键字搜索内容,但是某些关键字不允许被搜索。这些不能被搜索的关键字会被放在一个黑名单当中,黑名单每天晚上更新一次。当用户搜索时,会检查当前关键字在不在黑名单当中,如果在,则提示不能搜索。

注意

  1. 减少扩容开销。根据实际需要,初始化CopyOnWriteMap的大小,避免写时CopyOnWriteMap扩容的开销。
  2. 使用批量添加。因为每次添加,容器每次都会进行复制,所以减少添加次数,可以减少容器的复制次数。

5.4 缺点

  • 内存占用问题。因为CopyOnWrite的写时复制机制,所以在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象。
  • 数据一致性问题。CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。
  • 从上面那点,我想到另外一个知识点:volatile保证的是实时一致性。对比来看,CopyOnWriteArrayList的底层结构未使用volatile关键字;CopyOnWriteMap使用了volatile,能够对map的引用保证实时一致性,可以理解成对数据也是实时一致性的。

Java.lang.NoClassDefFoundError 的解决方法 Java.lang.NoClassDefFoundError 的解决方法Java开发过程中,经常会遇到 java.lang.NoClassDefFoundError 错误。这个错误通常表示在运行时找不到所需的类。本文将探讨这个问题的原因,并提供一些解决方案。 阅读详情

相关推荐

JUC(十)

写时复制容器--CopyOnWrite&CopyOnWriteArrayList原理

xp_xpxp的博客 302

周期工具任务类,可随时添加和修改任务

import com.sun.jersey.client.impl.CopyOnWriteHashMap; import javax.validation.constraints.NotNull; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledF...

qq_35387405的博客 636

flink依赖jar包——解决NoClassDefFoundError: com/sun/jersey

当flink on yarn模式运行时,发生如下异常信息,需要将压缩包中的4个依赖jar包放入flink安装路径下的lib目录下。 Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig at org.apache.hadoop.yarn.client.api.TimelineClient.createTimelineClient(TimelineClient.java:45) at org.apache.hadoop.yarn.client.api.impl.YarnClientImpl.serviceInit(YarnClientImpl.java:163) at org.apache.hadoop.service.AbstractService.init(AbstractService.java:163) at org.apache.spark.deploy.yarn.Client.submitApplication(Client.scala:150) at org.apache.spark.scheduler.cluster.YarnClientSchedulerBackend.start(YarnClientSchedulerBackend.scala:56) ... Caused by: java.lang.ClassNotFoundException: com.sun.jersey.api.client.config.ClientConfig

CopyOnWrite线程安全集合

一、CopyOnWrite集合简介 CopyOnWrite集合包括CopyOnWriteArrayList,CopyOnWriteSet和CopyOnWriteHashMap,但CopyOnWriteHashMap使用较少,并发环境大多采用性能更高的cpncurrentHashMap。其实现线程安全的核心思想是读写分离,即在写的时候,将底层的数组拷贝一份,然后修改拷贝的数组,再将修改后的数组通过原子操作的方式赋值给底层数组,以实现线程安全 二、CopyOnWriteArrayList 2-1 底层结构

weixin_44105468的博客 3317

避开这5个坑!ADNI数据库下载实操经验分享(含断点续传方案)

本文分享了ADNI数据库下载的5个常见陷阱及解决方案,包括高级搜索策略优化、断点续传技巧和数据完整性验证。特别针对大文件下载中断问题,提供了wget断点续传和分卷下载的实操方法,帮助研究者高效获取神经影像数据,避免重复下载和时间浪费。

git9versioner的博客 374

粒子滤波在基于误差状态量的INS/GNSS组合导航中的使用技巧-On Particle Filter based Error-State INS/GNSS Intergrated Navigation

本文面向以15维惯导(INS)误差为状态量,3维位置误差为量测量的INS/GNSS组合导航系统,​在西工大严恭敏老师的开源工具箱中PF相关库函数基础上实现基于粒子滤波(PF)的惯导误差状态量的递推估计,设计了粒子重置环节并强调了其在本特定场景下的重要性。

I33D33I的博客 1742

copyonwrite思想

不了解这些“高级货”,活该你面试当炮灰。。。【石杉的架构笔记】 原创: 中华石杉 公众号后台回复“资料” 获取作者独家秘制学习资料 目录 1.读多写少的场景下引发的问题? 2.引入 CopyOnWrite 思想解决问题! 3.CopyOnWrite思想在Kafka源码中的运用 “今天聊一个非常硬核的技术知识,给大家分析一下CopyOnWrite思想...

疯一样的女子 532

hcaptcha-challenger:基于本地AI模型自动破解验证码的工程实践

验证码作为区分人类与机器的经典安全机制,其核心原理是通过图像识别、行为分析等交互式挑战来阻挡自动化程序。传统绕过方法依赖第三方打码平台或脚本,存在成本高、稳定性差的问题。随着多模态大语言模型和计算机视觉技术的发展,本地化AI求解成为新的技术方向,它通过集成YOLO、ResNet等模型,在本地完成图像语义理解,实现了高隐私、低成本、可进化的验证码自动化解决方案。这种范式尤其适用于需要大规模稳定处理网页交互的场景,如电商数据采集和社交媒体管理。hcaptcha-challenger项目正是这一理念的工程实践,它

weixin_42587866的博客 1028

CopyOnWrite机制

前言 CopyOnWrite机制它的核心思想:读写分离,空间换时间,避免为保证并发安全导致的激烈的锁竞争。 划关键点: CopyOnWrite适用于读多写少的情况,最大程度的提高读的效率; CopyOnWrite是最终一致性,在写的过程中,原有的读的数据是不会发生更新的,只有新的读 才能读到最新数据; 如何使其他线程能够及时读到新的数据,需要使用volatile变量; 写的时候不能并发写,需要对写操作进行加锁; 二、使用步骤 /** * Appends the

qq_49281137的博客 866

逆变器专题(6)-正负序分离(二阶广义积分器DSOGI)

相应仿真原件请移步资源下载DSOGI作为一种常用的正负序分离方法,其可以在电压三相不平衡的状态下实现较为精准的锁相环。

cyc19980105的博客 8807

星宸科技SSD20x/SSD21X应用层DEMO实战指南:从入门到深度定制

本文详细介绍了星宸科技SSD20x/SSD21X系列芯片的应用层DEMO开发实战,从基础环境搭建到深度定制开发。内容涵盖DEMO资源获取、核心功能实现、第三方库集成以及性能优化技巧,帮助开发者快速掌握智能显示和多媒体处理应用的开发方法。特别适合嵌入式开发者在智能家居、工业控制等场景中应用。

weixin_42524226的博客 268

CopyOnWrite 思想

通过思想实现了在读多写少的并发场景下的高效性。它通过复制原始数据结构来避免在写操作时对读操作造成干扰,同时使用内部锁和快速失败的迭代器来保证线程安全。然而,由于写操作的开销较大,它不适合用于高并发写入的场景。在使用时,应当根据实际的应用场景和性能需求来决定是否采用。

夜尽天明 560

二、基于C语言的JPEG解码代码详解

// JPEG解码 // 输入JPEG后输出Bitmap #include <stdio.h> #include <stdlib.h> #pragma warning(disable : 4996) unsigned int BuffIndex; // JPEG数据的位置 unsigned int BuffSize; // JPEG数据的大小 unsigned int BuffX; // 图像的横向尺寸 unsigned int BuffY; //

m0_37633745的博客 4458

synchronized vs CopyOnWrite 系列

并发编程中解决共享数据问题的两条核心路径:互斥锁(synchronized)和写时复制(CopyOnWrite)。前者通过对象头和监视器实现锁升级机制,提供强一致性但影响吞吐量;后者以空间换时间,读写分离实现无锁读但写性能较差。synchronized采用偏向锁、轻量级锁和重量级锁的渐进式优化,保证内存可见性;CopyOnWrite通过volatile引用和数组复制实现线程安全。两种方案分别适用于写密集型和读密集型场景,开发者需根据业务特点权衡选择。

写代码写久了才发现:人生和程序一样,经常 Bug 多、需求乱,重构难,但总能跑起来。这个博客记录我从迷茫到搞懂、从踩坑到归纳、从混乱到清晰的过程。写给过去迷茫的自己,也写给同样在路上折腾的你。没有炫技,没有玄学,只有真实的思考、实践和成长。 1022

OpenCV轮廓匹配实战:5分钟搞定Hu矩形状识别(附完整代码)

本文详细介绍了使用OpenCV进行轮廓匹配的实战技术,重点讲解了Hu矩形状识别在工业质检等领域的应用。通过完整的代码示例和参数调优技巧,帮助开发者在5分钟内实现高效的形状识别,提升工业检测的准确性和效率。

nnn11的博客 676

“华为杯”研究生数学建模竞赛2017年-【华为杯】B题:面向下一代光通信的 VCSEL 激光器仿真模型

得出以下主要结论:在相同的偏置电流条件下,随着温度的升高,带宽的峰值向。在相同的温度下,随着电流的增大,带宽的峰值越小且曲线由波峰形状。方案,包括可能的数学公式,不同温度和偏置电流下的带宽响应曲线,并与问题。线,得出以下主要结论:在相同的偏置电流条件下,随着温度的升高,带宽的峰。在相同的温度下,随着电流的增大,带宽的峰值越小且曲线由波峰形状逐渐变得。得的激光器特性曲线和模型中仿真得到的特性曲线,之后,可以将两组曲线的差。说明的是,由于数值优化算法的成功与否很大程度上依赖于初始参数的猜测,参。

getusushu的博客 99

java高并发锁的3种实现示例代码

初级技巧 - 乐观锁 乐观锁适合这样的场景:读不会冲突,写会冲突。同时读的频率远大于写。 以下面的代码为例,悲观锁的实现: public Object get(Object key) { synchronized(map) { if(map.get(key) == null) { // set some values } return map.get(k...

上善若水 3617

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

CopyOnWrite容器

####

m0_59031879的博客 339

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

sheng的学习笔记-锁-写入时复制copyOnWrite

copy on write策略

coldstarry的专栏 390

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

java arraycopy 并发_java并发面试常识之copyonwrite

今天在网上看到一个问题,问除了加锁之外有没有其他方法来保证线程安全。楼下很多回答copyonwrite机制。这个问题回答有很多,但是copyonwrite的回答有点误导人。copyonwrite机制和单词描述的一样,他的实现就是写时复制, 在往集合中添加数据的时候,先拷贝存储的数组,然后添加元素到拷贝好的数组中,然后用现在的数组去替换成员变量的数组(就是get等读取操作读取的数组)。这个机制和读写...

weixin_39642619的博客 149

day-3-1-2

java ConcurrentHashMap

haodi12138的博客 177

ConcurrentHashMap

ConcurrentHashMap 特点 并发安全集合,存在多线程访问的情况下使用的集合工具;另外这种也行【Collections.synchronizedMap();】,将非现场安全转为线程安全。 CHM 中是支持并发扩容的,也就是说如果当前的数组需要进行扩容操作,可以由多个线程来共同负责。 扩容是 ConcurrentHashMap 的精华之一,扩容操作的核心在于数据的转移,在单线程环境下数据的转移很简单,无非就是把旧数组中的数据迁移到新的数组。但是这在多线程环境下,在扩容的时候其他线程也可能正在添加

轻描淡写 377

同步类容器和并发类容器

** 同步类容器 ** 同步类容器都是线程安全的,同步容器类包括 Vector 和 HashTable,二者都是早期 JDK 的一部分,此外还包括在 JDK1.2 当中添加的一些功能相似的类,这些同步的封装类是由 Collections.synchronizedXxx 等工厂方法创建的。 但在某些场景下可能需要加锁来保护复合操作。复合类操作如:迭代(反复访问元素, 遍历完容器中所有的元素)、跳转(根据指定的顺序找到当前元素的下一个元素)、以及条件运算。这些复合操作在多线程并发地修改容器时,可能会表现出意外的

wjf_jone的博客 218

java clone 线程安全_Java集合--线程安全(CopyOnWrite机制)

5 Java并发集合5.1 引言在前几章中,我们介绍了Java集合的内容,具体包括ArrayList、HashSet、HashMap、ArrayQueue等实现类。不知道各位有没有发现,上述集合都有一个共同的特点,那就是线程不安全性,在并发情况下都不能保证数据的一致性。(当然,这个集合必须是共享了,所以才会有数据不一致)所以,当我们在进行并发任务时候,共享了一个不适用于并发的数据结构,也就是将此数...

weixin_42491621的博客 216

Java同步并发容器类

同步容器类包括vector和Hashtable。此外还包括jdk1.2中添加的一些功能相似的类,这些同步封装器是由Collections.synchronizedXxx等工厂方法创建的。这些类实现线程安全的方式是:将它们的状态封装起来,并对每个共有方法都进行同步,使得每次只有一个线程能访问容器的状态。同步容器类的问题 同步容器类都是线程安全的,但在某些情况下可能需要额外的客户端加锁来保护复合操作。

漫长学习路 2231

Java多线程(8) - 同步(并发)类容器详解(CopyOnWrite容器、ConcurrentMap容器、Queue队列容器)

同步(并发)类容器 同步(并发)类容器都是线程安全的,但在某些场景下可能需要加锁来保护复合操作,如迭代(反复访问元素,遍历容器所有元素)、跳转(根据指定的顺序找到当前元素的下一个元素),以及条件运算。 这些复合操作在多线程并发的修改容器时,可能会表现出意外的行为,最典型的就是之前解析集合源码时,讲到的Fast-Fast机制,会抛出ConcurrentModificationException异常,这是早期迭代器设计的时候并没有考虑并发修改的问题。 早期的同步(并发)...

Su_Levi_Wei的博客 506
上一篇: 第三篇:GPU 并行编程的运算架构
下一篇: C++:线程(std::thread)
Poo_Chai
博客等级 码龄9年 178粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值