Java 多线程之 ReentrantReadWriteLock(读写锁/共享锁/排他锁)

文章目录

    • 一、概述
    • 二、使用方法
    • 三、测试示例
    • 四、完整示例

一、概述

  • ReentrantReadWriteLock 是Java中提供的一种读写锁实现,它允许多个线程同时读取共享资源,但在写操作时需要独占访问。它是对传统互斥锁的一种改进,可以提高并发性能。

  • 读写锁的主要目的是在读多写少的场景下,提供更高的并发性能。当多个线程只需读取共享资源时,可以同时获得读锁,从而实现并发读取。而当有线程需要对共享资源进行写操作时,它必须独占地获取写锁,在此期间,其他线程无法获取读锁或写锁,从而确保数据的一致性和完整性。

  • 读写锁的特性如下:

    • 1、多个线程可以同时获取读锁,进行并发读取操作。
    • 2、当某个线程获取写锁时,其他线程无法获取读锁或写锁,必须等待写锁释放。
    • 3、写锁是独占锁,只能被一个线程获取,用于保证数据一致性。
    • 4、ReadWriteLock 接口提供了两个关键的方法:
      • (1)readLock():返回一个读锁对象,用于读取共享数据。
      • (2)writeLock():返回一个写锁对象,用于写入共享数据。

二、使用方法

  • 创建一个ReentrantReadWriteLock对象

    ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    
  • 获取读锁

    rwLock.readLock().lock();
    try {// 访问共享资源的读操作
    } finally {rwLock.readLock().unlock();
    }
    
  • 获取写锁

    rwLock.writeLock().lock();
    try {// 访问共享资源的写操作
    } finally {rwLock.writeLock().unlock();
    }
    

三、测试示例

  • SharedData 类使用 ReentrantReadWriteLock 实现了读写锁机制。多个线程可以同时获取读锁进行读操作,但只有一个线程可以获取写锁进行写操作,以提高读操作的并发性能。

    class SharedData {private Map<String, String> data = new HashMap<>();private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public void put(String key, String value) {lock.writeLock().lock();try {data.put(key, value);} finally {lock.writeLock().unlock();}}public String get(String key) {lock.readLock().lock();try {return data.get(key);} finally {lock.readLock().unlock();}}
    }
    
  • 测试方法:创建1个写线程,10个读线程。模拟读多写少的场景。

        private void test(){SharedData data = new SharedData();List<Thread> threads = new ArrayList();for(int i = 1; i<= 1; i++){Thread t = new Thread(()->{for(int j=0; j< 100000; j++){try {String text = Thread.currentThread().getName()+" 写数据 "+ j;data.put("SharedData", text);System.out.println(text);Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}});t.setName("写线程"+i);threads.add(t);}for(int i = 1; i<= 10; i++){Thread t = new Thread(()->{for(int j=0; j< 100000; j++){try {String result = data.get("SharedData");System.out.println(Thread.currentThread().getName()+" 读取 "+result);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.setName("读线程"+i);threads.add(t);}for(Thread t : threads){t.start();}for(Thread t : threads){try {t.join();} catch (InterruptedException e) {e.printStackTrace();}}}
    

四、完整示例

  • 以下是完整示例代码

    package top.yiqifu.study.p004_thread;import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.locks.ReentrantReadWriteLock;public class Test062_ReentrantReadWriteLock {public static void main(String[] args) {Test062_ReentrantReadWriteLock test = new Test062_ReentrantReadWriteLock();test.test();}private void test(){SharedData data = new SharedData();List<Thread> threads = new ArrayList();for(int i = 1; i<= 1; i++){Thread t = new Thread(()->{for(int j=0; j< 100000; j++){try {String text = Thread.currentThread().getName()+" 写数据 "+ j;data.put("SharedData", text);System.out.println(text);Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}});t.setName("写线程"+i);threads.add(t);}for(int i = 1; i<= 10; i++){Thread t = new Thread(()->{for(int j=0; j< 100000; j++){try {String result = data.get("SharedData");System.out.println(Thread.currentThread().getName()+" 读取 "+result);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.setName("读线程"+i);threads.add(t);}for(Thread t : threads){t.start();}for(Thread t : threads){try {t.join();} catch (InterruptedException e) {e.printStackTrace();}}}class SharedData {private Map<String, String> data = new HashMap<>();private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public void put(String key, String value) {// 写锁lock.writeLock().lock();try {data.put(key, value);} finally {lock.writeLock().unlock();}}public String get(String key) {// 读锁lock.readLock().lock();try {return data.get(key);} finally {lock.readLock().unlock();}}}}

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

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

相关文章

C#开发的OpenRA游戏之属性SelectionDecorations(13)

C#开发的OpenRA游戏之属性SelectionDecorations(13) 在前面分析SelectionDecorations属性类时,会发现它有下面这个属性: public class SelectionDecorations : SelectionDecorationsBase, IRender { readonly Interactable interactable; 它是定义了一个Interactabl…

【编写UI自动化测试集】Appium+Python+Unittest+HTMLRunner​

简介 获取AppPackage和AppActivity 定位UI控件的工具 脚本结构 PageObject分层管理 HTMLTestRunner生成测试报告 启动appium server服务 以python文件模式执行脚本生成测试报告 下载与安装 下载需要自动化测试的App并安装到手机 获取AppPackage和AppActivity 方法一 有源码…

怎么安装php扩展

在Windows环境下安装PHP扩展&#xff1a; 下载扩展&#xff1a; 对于一些常见的扩展&#xff0c;可以在官方的PHP网站上找到预编译的DLL文件。前往PECL或者PHP官网来下载相应版本的DLL文件。 更新php.ini配置文件&#xff1a; 找到PHP的安装目录&#xff0c;并且打开php.ini文…

大杀四方,华为组建智能车大联盟 | 百能云芯

最近&#xff0c;华为和一系列汽车公司合资的新公司迎来新的进展。除了与长安汽车的合作外&#xff0c;据传华为已经邀请奇瑞、赛力斯、北汽以及江淮汽车入股新公司&#xff0c;这将使华为成为中国智能汽车平台的重要主导者。 根据澎湃新闻的报道&#xff0c;知情人透露&#x…

Java EE 多线程

文章目录 1. 认识线程1.1 什么是进程1.2 什么是线程1.2.1. 线程是怎么做到的呢&#xff1f;1.2.2. 进程和线程的关系 1.3 多线程编程1.3.1. 第一个多线程程序1.3.2. 使用 jconsole 命令查看线程1.3.3. 实现 Runnable 接口&#xff0c;重写 run1.3.4. 继承 Thread 重写 run&…

2023-11-29 Linux环境创建命名管道小实验

点击 <C 语言编程核心突破> 快速C语言入门 Linux环境创建命名管道小实验 前言一、mkfifo()函数AI助手提供协作二、代码总结 前言 要解决问题: Linux环境用mkfifo()创建个管道, 但是被阻塞, 发现是管道虽然建立了, 但是没有进程打开它, 以至于阻塞. 想到的思路: 开始时…

悲观锁乐观锁在django中使用

1 悲观锁乐观锁 1.1 并发控制 1.1 悲观锁 1.2 乐观锁 1.3 悲观锁乐观锁使用场景 2 django中开启事务 2.1 全局开启事务 2.2 视图开启事务 2.3 局部使用事务 2.4 savepoint回滚 2.5 事务提交后回调函数 3 django中使用悲观锁 3.1 前置条件&#xff0c;表模型 3.1 模拟秒杀生成…

配电网重构单时段+多时段(附带matlab代码)

配电网重构单时段多时段 对于《主动配电网最优潮流研究及其应用实例》的基本复现 简介&#xff1a;最优潮流研究在配电网规划运行中不可或缺&#xff0c;且在大量分布式能源接入的主动配电网环境下尤为重要。传统的启发式算法在全局最优解和求解速度上均无法满足主动配电网运行…

八股文-如何理解Java中的多态

什么是多态&#xff1f; 多态是面向对象编程的一个重要概念&#xff0c;它允许一个对象以不同的形式表现。也就是说&#xff0c;在父类中定义的属性和方法&#xff0c;在子类继承后&#xff0c;可以有不同的数据类型或表现出不同的行为。这可以使得同一个属性或方法&#xff0…

读书笔记:彼得·德鲁克《认识管理》第34章 结构与战略

一、章节内容概述 在现代管理的短暂历史上&#xff0c;我们曾经两次相信找到了正确答案。一 次是第一次世界大战时期亨利法约尔构建的“职能制组织”&#xff0c;另一次是 一代人时间后阿尔弗雷德斯隆构建的“联邦分权制组织”。在适当的领 域和条件下&#xff0c;这两种组织结…

操作系统 day14(进程同步、进程互斥)

进程同步 概念 进程的异步性体现在&#xff0c;例如&#xff1a;当有I/O操作时&#xff0c;进程需要等待I/O操作&#xff0c;而每个I/O操作又是不同的&#xff0c;所以进程没有一个固定的顺序&#xff0c;固定的时间来执行&#xff0c;而这体现了进程的异步性。 进程互斥 …

freeRTOS异常处理函数分析(以RISC-V架构进行分析)

1、异常处理函数的注册 对RISC-V架构中断不熟悉&#xff0c;可参考博客&#xff1a;《RISC-V架构——中断处理和中断控制器介绍》&#xff1b; 2、异常处理函数分析 2.1、数调用关系 freertos_risc_v_trap_handler //异常处理函数入口portcontextSAVE_CONTEXT_INTERNAL //保存…

Python-pip配置国内镜像源,快速下载包

文章目录 国内镜像源临时使用永久配置添加环境变量Path测试关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 国内…

零代码连接钉钉宜搭与用友U8,让业财数据管理简单高效

零代码连接钉钉宜搭与用友U8&#xff0c;让业财数据管理简单高效 如果把企业内部的业务系统比作一条条河流&#xff0c;那么它们的交汇点就像江河湖海。在这些交汇点上&#xff0c;数据的汇集、分析和共享离不开系统之间的集成。 钉钉宜搭和用友U8是两个在企业中非常重要的系统…

实现电商平台与营销系统无缝集成:雅座的无代码开发与API连接

无代码开发&#xff1a;营销的新引擎 在数字化转型的浪潮中&#xff0c;无代码开发已成为企业提升效率、减少成本的新引擎。这种开发方式允许非技术人员通过图形界面构建应用程序&#xff0c;无需编写代码即可实现复杂功能。这对于营销、广告推广以及用户运营等业务尤为重要&a…

wvp 视频监控平台抓包分析

抓包时机 下面的抓包时机是抓包文件最新&#xff0c;但是最有用的包 选择网卡开始抓包 如果之前已经选择网卡&#xff0c;直接开始抓包 停止抓包 重新抓包 sip播放过程分析 过滤条件 tcp.port 5060 and sip 可以看到有这些包 选择任何一个 &#xff0c;戍边右键--追踪流--…

JDK21下载+安装+环境配置教程(Windows系统)

前言&#xff1a;甲骨文公司与2023.9发布JDK21,JDK21将是一个长期支持&#xff08;LTS&#xff09;版本&#xff0c;JDK20目前可以从官网下载使用。 1&#xff0c;搜索Oracle官网找到JDK21 Java Downloads | Oracle 2&#xff0c;切换Windows系统&#xff0c;然后点击下载&am…

记录vue2组件传值props的两种写法

在写传值时候发现了props的对象和数组类型写法&#xff0c;不知道有什么差距就查了一下 props: ["testMsg",] 这种方式是使用数组的形式来定义props&#xff0c;其中数组的元素是要传递的属性名称。在子组件中&#xff0c;可以通过this.$props来访问这些属性 <…

Mysql 不执行索引问题与优化

难以查找的隐藏问题 及 解决办法&#xff1a; 问题总结&#xff1a;

项目demo —— GPT 聊天机器人

本文介绍我的开源项目 TelegramChatBot&#xff0c;这是一个基于 OpenAI GPT API 开发的 telegram 机器人&#xff0c;具有多模态交互能力&#xff0c;求 star&#xff01;感谢大家&#xff01;在 telegram jokerController_bot 立即体验&#xff01;欢迎对 GPT 应用开发或对 t…