当前位置: 首页 > news >正文

读写锁: ReentrantReadWriteLock

在多线程编程场景中,对共享资源的访问控制极为关键。传统的锁机制在同一时刻只允许一个线程访问共享资源,这在读写操作频繁的场景下,会因为读操作相互不影响数据一致性,而造成不必要的性能损耗。ReentrantReadWriteLock(可重入读写锁)的出现有效解决了这一问题,它允许在同一时间内多个线程进行读操作,同时保证写操作的原子性与线程安全性。本文将深入探讨ReentrantReadWriteLock的原理、使用方式及其应用场景。

ReentrantReadWriteLock 原理剖析

ReentrantReadWriteLock是 Java 并发包java.util.concurrent.locks中的成员,它将对共享资源的访问分为读锁和写锁。读锁允许多个线程同时获取,因为读操作不会修改共享资源,所以多个线程同时读不会产生数据不一致问题。而写锁是独占的,同一时间仅能有一个线程获取写锁,以此保证写操作的原子性和线程安全。

可重入特性

ReentrantReadWriteLock具备可重入特性,即同一个线程能够多次获取读锁或写锁。当线程获取锁后,锁的持有计数会增加,每释放一次锁,持有计数就减少,当持有计数为 0 时,锁才真正被释放。该特性避免了线程在递归调用时出现死锁情况。

公平性与非公平性

ReentrantReadWriteLock支持公平和非公平两种模式。在公平模式下,线程获取锁的顺序依照请求的先后顺序进行;在非公平模式下,线程获取锁的顺序不确定,新请求的线程有可能比等待队列中的线程更早获取到锁。非公平模式在高并发场景下通常性能更佳,因为它减少了线程切换的开销。

代码示例

以下通过一个简单示例代码展示ReentrantReadWriteLock的基本用法。假设存在一个共享缓存,多个线程可能读取缓存中的数据,也可能更新缓存。

import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockExample {private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();private static final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();private static final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();private static String cacheData;public static void main(String[] args) {// 模拟读线程Thread readThread1 = new Thread(() -> {readLock.lock();try {System.out.println(Thread.currentThread().getName() + " 开始读取数据");if (cacheData == null) {System.out.println("缓存中没有数据");} else {System.out.println("读取到的数据: " + cacheData);}Thread.sleep(1000);System.out.println(Thread.currentThread().getName() + " 读取数据结束");} catch (InterruptedException e) {e.printStackTrace();} finally {readLock.unlock();}});// 模拟写线程Thread writeThread1 = new Thread(() -> {writeLock.lock();try {System.out.println(Thread.currentThread().getName() + " 开始写入数据");cacheData = "新的数据";System.out.println(Thread.currentThread().getName() + " 写入数据结束");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {writeLock.unlock();}});readThread1.start();writeThread1.start();try {readThread1.join();writeThread1.join();} catch (InterruptedException e) {e.printStackTrace();}}
}

在上述代码中:

  1. 首先创建了ReentrantReadWriteLock对象,以及它的读锁和写锁。
  2. readThread1线程模拟读操作,获取读锁后,尝试读取缓存数据。由于读锁允许多个线程同时获取,所以多个读线程可以同时执行读操作。
  3. writeThread1线程模拟写操作,获取写锁后,更新缓存数据。在写锁被持有期间,其他线程无论是读还是写操作,都将被阻塞,直到写锁被释放。

使用场景

  1. 缓存系统:在缓存系统中,读操作的频率通常远高于写操作。使用ReentrantReadWriteLock可以允许多个线程同时读取缓存,只有在更新缓存时才需要获取写锁,从而大大提高系统的并发性能。
  2. 数据库连接池:数据库连接池需要管理多个数据库连接,多个线程可能会同时获取和释放连接信息。通过ReentrantReadWriteLock,读操作(如获取连接状态)可以并发执行,而写操作(如添加或移除连接)则保证线程安全。
  3. 文件系统:在文件系统中,多个线程可能会同时读取文件内容,而写操作(如文件修改)则需要保证原子性。ReentrantReadWriteLock可以有效管理对文件的读写访问,确保数据的一致性。

结语

感谢您的阅读!如果您对 ReentrantReadWriteLock 或其他并发编程话题有任何疑问或见解,欢迎继续探讨。

相关文章:

读写锁: ReentrantReadWriteLock

在多线程编程场景中,对共享资源的访问控制极为关键。传统的锁机制在同一时刻只允许一个线程访问共享资源,这在读写操作频繁的场景下,会因为读操作相互不影响数据一致性,而造成不必要的性能损耗。ReentrantReadWriteLock&#xff0…...

上海路网道路 水系铁路绿色住宅地工业用地面图层shp格式arcgis无偏移坐标2023年

标题和描述中提到的资源是关于2023年上海市地理信息数据的集合,主要包含道路、水系、铁路、绿色住宅区以及工业用地的图层数据,这些数据以Shapefile(shp)格式存储,并且是适用于ArcGIS软件的无偏移坐标系统。这个压缩包…...

爬虫学习笔记之Robots协议相关整理

定义 Robots协议也称作爬虫协议、机器人协议,全名为网络爬虫排除标准,用来告诉爬虫和搜索引擎哪些页面可以爬取、哪些不可以。它通常是一个叫做robots.txt的文本文件,一般放在网站的根目录下。 robots.txt文件的样例 对有所爬虫均生效&#…...

Python小游戏29乒乓球

import pygame import sys # 初始化pygame pygame.init() # 屏幕大小 screen_width 800 screen_height 600 screen pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("打乒乓球") # 颜色定义 WHITE (255, 255, 255) BLACK (…...

220.存在重复元素③

目录 一、题目二、思路三、解法四、收获 一、题目 给你一个整数数组 nums 和两个整数 indexDiff 和 valueDiff 。 找出满足下述条件的下标对 (i, j)&#xff1a; i ! j, abs(i - j) < indexDiff abs(nums[i] - nums[j]) < valueDiff 如果存在&#xff0c;返回 true &a…...

使用 Go 语言调用 DeepSeek API:完整指南

引言 DeepSeek 是一个强大的 AI 模型服务平台&#xff0c;本文将详细介绍如何使用 Go 语言调用 DeepSeek API&#xff0c;实现流式输出和对话功能。 Deepseek的api因为被功击已不能用&#xff0c;本文以 DeepSeek&#xff1a;https://cloud.siliconflow.cn/i/vnCCfVaQ 为例子进…...

AJAX笔记原理篇

黑马程序员视频地址&#xff1a; AJAX-Day03-01.XMLHttpRequest_基本使用https://www.bilibili.com/video/BV1MN411y7pw?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p33https://www.bilibili.com/video/BV1MN411y7pw?vd_sour…...

ubuntu直接运行arm环境qemu-arm-static

qemu-arm-static 嵌入式开发有时会在ARM设备上使用ubuntu文件系统。开发者常常会面临这样一个问题&#xff0c;想预先交叉编译并安装一些应用程序&#xff0c;但是交叉编译的环境配置以及依赖包的安装十分繁琐&#xff0c;并且容易出错。想直接在目标板上进行编译和安装&#x…...

尝试把clang-tidy集成到AWTK项目

前言 项目经过一段时间的耕耘终于进入了团队开发阶段&#xff0c;期间出现了很多问题&#xff0c;其中一个就是开会讨论团队的代码风格规范&#xff0c;目前项目代码风格比较混乱&#xff0c;有的模块是驼峰&#xff0c;有的模块是匈牙利&#xff0c;后面经过讨论&#xff0c;…...

一文了解性能优化的方法

背景 在应用上线后&#xff0c;用户感知较明显的&#xff0c;除了功能满足需求之外&#xff0c;再者就是程序的性能了。因此&#xff0c;在日常开发中&#xff0c;我们除了满足基本的功能之外&#xff0c;还应该考虑性能因素。关注并可以优化程序性能&#xff0c;也是体现开发能…...

【怎么用系列】短视频戒断——对推荐算法进行干扰

如今推荐算法已经渗透到人们生活的方方面面&#xff0c;尤其是抖音等短视频核心就是推荐算法。 【短视频的危害】 1> 会让人变笨&#xff0c;慢慢让人丧失注意力与专注力 2> 让人丧失阅读长文的能力 3> 让人沉浸在一个又一个快感与嗨点当中。当我们刷短视频时&#x…...

C#中的委托(Delegate)

什么是委托? 首先,我们要知道C#是一种强类型的编程语言,强类型的编程语言的特性,是所有的东西都是特定的类型 委托是一种存储函数的引用类型,就像我们定义的一个 string str 一样,这个 str 变量就是 string 类型. 因为C#中没有函数类型,但是可以定义一个委托类型,把这个函数…...

PostCss

什么是 PostCss 如果把 CSS 单独拎出来看&#xff0c;光是样式本身&#xff0c;就有很多事情要处理。 既然有这么多事情要处理&#xff0c;何不把这些事情集中到一起统一处理呢&#xff1f; PostCss 就是基于这样的理念出现的。 PostCss 类似于一个编译器&#xff0c;可以将…...

Linux 系统上安装 Docker 并进行配置

Docker 是一种开源的应用容器引擎&#xff0c;它允许开发者打包他们的应用以及应用的依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不会有任何接口&#xff08;类似 iPh…...

DeepSeek 等 AI 技术能否推动股市的繁荣?

在科技浪潮汹涌澎湃的当下&#xff0c;DeepSeek 等 AI 技术宛如闪耀在天际的耀眼星辰&#xff0c;吸引着全球各界的高度关注。面对这些前沿技术&#xff0c;投资者和市场参与者心中不禁泛起疑问&#xff1a;它们是否能成为推动股市繁荣的强劲动力&#xff1f;这一问题不仅左右着…...

【网络】应用层协议http

文章目录 1. 关于http协议2. 认识URL3. http协议请求与响应格式3.1 请求3.2 响应 3. http的常见方法4. 状态码4.1 常见状态码4.2 重定向 5. Cookie与Session5.1 Cookie5.1.1 认识Cookie5.1.2 设置Cookie5.1.3 Cookie的生命周期 5.2 Session 6. HTTP版本&#xff08;了解&#x…...

大数据数仓实战项目(离线数仓+实时数仓)2

1.课程目标和课程内容介绍 2.数仓维度建模设计 3.数仓为什么要分层 4.数仓分层思想和作用 下面是阿里的一种分层方式 5.数仓中表的种类和同步策略 6.数仓中表字段介绍以及表关系梳理 订单表itcast_orders 订单明细表 itcast_order_goods 商品信息表 itcast_goods 店铺表 itcast…...

测试csdn图片发布

测试csdn图片发布 ​​...

站在JavaScript的视角去看,HTML的DOM和GLTF的Json数据。

很多前端小伙伴没有见过、操作过gltf文件&#xff0c;对非常懵逼&#xff0c;本文从前端小伙伴最熟悉的dom模型为切入口&#xff0c;以类别的方式来学习一下gltf文件。 一、结构与组织形式 HTML DOM&#xff08;文档对象模型&#xff09;&#xff1a; 树形结构&#xff1a;HT…...

传输层协议 UDP 与 TCP

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 前置复盘&#x1f98b; 传输层&#x1f98b; 再谈端口号&#x1f98b; 端口号范围划分&#x1f98b; 认识知名端口号 (Well-Know Port Number) 二&#xf…...

独立开发者利用Taotoken统一API开发跨模型内容生成应用案例

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 独立开发者利用Taotoken统一API开发跨模型内容生成应用案例 应用场景类&#xff0c;一位独立开发者希望构建一个能同时调用多种大模…...

如何实现微信聊天记录永久保存:WeChatMsg完整备份终极指南

如何实现微信聊天记录永久保存&#xff1a;WeChatMsg完整备份终极指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/W…...

Simulink仿真避坑指南:PWM控制48V直流电机时,轻载和重载下的参数设置与波形分析(附2018a源文件)

Simulink仿真避坑指南&#xff1a;PWM控制48V直流电机时&#xff0c;轻载和重载下的参数设置与波形分析 在工程实践中&#xff0c;直流电机的仿真建模是验证控制算法和预测系统性能的关键环节。特别是当面对不同负载条件时&#xff0c;如何准确设置电机参数并解读仿真波形&…...

C语言-指针二

一. 指针的操作int main() {int a 10 , b 20, c 30;int *p NULL, *q NULL;p &a;//对指针变量p本身进行修改b *p;//*p为右值表示对变量a的读取*p 60;//*p为左值表示通过指向的内存空间对变量a的写入p &c;//p指向的内存空间发生变化b *p;//对c的读取操作*p 70…...

AI驱动游戏开发:Godogen自动化流水线全解析

1. 项目概述&#xff1a;当AI成为你的游戏开发合伙人 如果你是一名独立游戏开发者&#xff0c;或者对用Godot引擎做点小玩意儿感兴趣&#xff0c;那你肯定体会过那种感觉&#xff1a;一个绝妙的点子在你脑海里盘旋&#xff0c;但一想到要从零开始搭场景、写脚本、画素材&#x…...

构建自我进化的AI家园:基于多智能体与GitOps的工程实践

1. 项目概述&#xff1a;构建一个能自我进化的AI家园如果你和我一样&#xff0c;对那种“一问一答”式的AI聊天机器人感到厌倦&#xff0c;总想着能不能让AI更“主动”一点&#xff0c;甚至能帮你打理整个技术栈&#xff0c;那么这个项目绝对值得你花时间研究。ai-homebase不是…...

工业通信网络实战:从工业以太网、IO-Link到智能工厂连接架构设计

1. 项目概述&#xff1a;智能工厂的“神经网络”革命如果你最近参观过任何一家现代化的汽车装配线或是消费电子产品的贴片车间&#xff0c;可能会被那些高度协同、几乎无人干预的自动化流程所震撼。机械臂精准地抓取、焊接、组装&#xff0c;AGV小车沿着无形的轨道穿梭运送物料…...

从单场到多场并发:知识竞赛平台的弹性扩展能力

&#x1f680; 从单场到多场并发&#xff1a;知识竞赛平台的弹性扩展能力动态调度 平滑扩容 稳定支撑&#x1f4cc; 演进中的需求&#xff1a;从单一活动到复杂场景传统的知识竞赛活动往往以单场、线下或小规模在线形式进行&#xff0c;对技术平台的压力相对有限。然而&#…...

深入T100系统腹地:拆解标准区、测试区与客制开发的协作逻辑

深入T100系统腹地&#xff1a;拆解标准区、测试区与客制开发的协作逻辑 在企业管理系统的复杂生态中&#xff0c;T100以其独特的四区架构和多环境协作机制&#xff0c;为企业的数字化转型提供了稳健的技术支撑。这套架构不仅关乎代码的流转&#xff0c;更是企业业务流程标准化与…...

Orama混合搜索实战:从全文检索到向量搜索的轻量级实现

1. 项目概述&#xff1a;从“全文搜索”到“向量搜索”的现代演进如果你做过Web开发&#xff0c;尤其是需要处理大量文本内容的应用&#xff0c;比如博客站、文档中心或者电商平台&#xff0c;那么“搜索”功能绝对是你绕不开的核心需求。传统上&#xff0c;我们可能会直接想到…...