读锁和写锁(共享锁和排他锁)介绍 以及相关类 ReentrantReadWriteLock 学习总结,使用场景

一、读锁和写锁概念

读锁
也称共享锁,多个线程可以共享资源,同时读取数据和资源,但是不允许出现写操作。多个线程可以同时持有读锁,提高并发性能,因为不会对数据修改。

写锁
也称排他锁,只允许一个线程独占地对共享资源进行写操作,其他线程无法同时持有写锁或读锁。写锁的目的是保证在写操作期间没有其他线程对资源进行读或写操作,从而确保数据的一致性。

使用场景
如果多个线程只需要读取共享资源而不进行修改,那么可以使用读锁来提高并发性能。
如果有线程需要修改共享资源,那么必须使用写锁来保证数据的一致性。

二、ReentrantReadWriteLock

ReentrantReadWriteLock 实现了 ReadWriteLock 接口,可以获取到读锁(共享锁),写锁(独占锁)。同时,通过构造方法可以创建锁本身是公平锁还是非公锁。
默认是非公平锁,性能也更好一点。构造方法传入 true 时为公平锁。

只有读锁与读锁之间是共享的,其他的读锁与写锁,写锁与写锁都是互斥的,不能同时持有。

2.1 线程进入读锁的前提条件:

  1. 不持有其他线程的写锁
  2. 没有写请求,或有写请求但调用线程和持有锁的线程是同一个

2.2 线程进入写锁的前提条件:

  1. 没有其他线程的读锁
  2. 没有其线程的写锁

2.3 锁升级和锁降级

ReentrantLock 具备可重入的能力,即同一个线程多次获取锁,不引起阻塞
那么 ReentrantReadWriteLock 关于可重入性需要额外知晓两个概念即锁升级和降级

锁升级:读锁变为写锁
锁降级:写锁变为读锁

重入时锁升级不支持:持有读锁的情况下去获取写锁会导致获取写锁永久等待,需要先释放读锁,再去获得写锁

重入时锁降级支持:持有写锁的情况下去获取读锁,造成只有当前线程会持有读锁,因为写锁会互斥其他的锁

2.4 使用介绍

构造方法
public ReentrantReadWriteLock():默认构造方法,非公平锁
public ReentrantReadWriteLock(boolean fair):true 为公平锁

常用API
public ReentrantReadWriteLock.ReadLock readLock():返回读锁
public ReentrantReadWriteLock.WriteLock writeLock():返回写锁

lock():加锁
unlock():解锁
tryLock():尝试获取锁

加解锁

        ReadWriteLock readWriteLock = new ReentrantReadWriteLock();Lock readLock = readWriteLock.readLock();readLock.lock();try {// ........ 临界区} finally {readLock.unlock();}

锁降级

w.lock();
try {r.lock();		// 降级为读锁, 释放写锁, 这样能够让其它线程读取缓存try {// ...} finally{w.unlock();		// 要在写锁释放之前获取读锁}
} finally{r.unlock();
}

2.5 运用场景

读写锁读多的写少的场景一般为使用缓存的场景。
即读取数据库中的数据到内存或者缓存中间件中,后期获取数据从缓存获取,当数据更新时需要同步更新缓存和数据库。

先清除缓存还是前更新数据库?
先清缓存:可能造成刚清理缓存还没有更新数据库,高并发下,其他线程直接查询了数据库过期数据到缓存中,这种情况非常严重,直接导致后续所有的请求缓存和数据库不一致。
先更新据库:可能造成刚更新数据库,还没清空缓存就有线程从缓存拿到了旧数据,这种情况概率比较小,影响范围有限,只对这一次的查询结果有问题。

实际在缓存中运用读写锁

public class CacheTest {// 缓存对象 这里使用一般map 放于内存Map<String, String> cache = new HashMap<>();// 创建读写锁ReadWriteLock readWriteLock = new ReentrantReadWriteLock();// 从缓存中获取数据 读操作public String getFromCache(String key) {// 加读锁,防止其他线程修改缓存即防止写操作readWriteLock.readLock().lock();try {String value = cache.get(key);// 缓存中存在 即缓存命中if(value != null) {return value;}} finally {// 释放读锁readWriteLock.readLock().unlock();}//如果缓存没有命中,从数据库中加载  加写锁readWriteLock.writeLock().lock();try {// 细节处理,为防止重复查询数据库, 再次验证  因为get 方法上面部分是可能多个线程进来的, 可能已经向缓存填充了数据String value = cache.get(key);if(value == null) {// 从数据库查询value = "从数据库中获取到数据并赋值 这里自行替换业务";cache.put(key, value);}return value;} finally {// 解锁写readWriteLock.writeLock().unlock();}}// 更新数据public void updateData(String key, String value) {// 加写锁readWriteLock.writeLock().lock();try {// 更新操作TODO 更新数据库// 清空缓存cache.remove(key);} finally {// 解锁写readWriteLock.writeLock().unlock();}}
}

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

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

相关文章

实战纪实 | 从接口信息泄露到RCE

打点 开局一个登录框 信息收集 发现了一处接口泄露了部分信息 不过只有支付宝密钥的信息无法扩大危害&#xff0c;此时尝试寻找了一下其他同类型系统同样的接口&#xff0c;查看一下是否泄露的信息相同 因为如果相同就说明是静态的&#xff0c;没有价值 横向收集 此时访问其…

后端系统开发之——接口参数校验

今天难得双更&#xff0c;大家点个关注捧个场 原文地址&#xff1a;后端系统开发之——接口参数校验 - Pleasure的博客 下面是正文内容&#xff1a; 前言 在上一篇文章中提到了接口的开发&#xff0c;虽然是完成了&#xff0c;但还是缺少一些细节——传入参数的校验。 即用户…

JMeter 并发测试和持续性压测详解

并发测试和持续性压测都是评估系统性能的常用方法&#xff0c;它们可以帮助开发人员发现并解决系统中的性能问题。本文来详细介绍下。 概念 并发测试&#xff1a; 旨在评估系统在同时处理多个用户请求时的性能。在这种 测试 中&#xff0c;系统会暴露于一定数量的用户负载下&…

【Flutter和H5数据传递问题】window.postMessage方法引起的数据问题

Flutter 前言问题双引号问题请求数据问题 总结 前言 距离上一篇博客已经过了很长时间了&#xff0c;这次在做公司项目中又遇到了新的问题&#xff0c;决定还是写出来看看各位大神对此有什么看法&#xff0c;分享一下各位的想法。 问题 首先&#xff0c;公司项目的框架是由Fl…

2024最新华为OD机试试题库全 -【执行时长】- C卷

1. 🌈题目详情 1.1 ⚠️题目 为了充分发挥GPU算力,需要尽可能多的将任务交给GPU执行,现在有一个任务数组,数组元素表示在这1秒内新增的任务个数且每秒都有新增任务。 假设GPU最多一次执行n个任务,一次执行耗时1秒,在保证GPU不空闲情况下,最少需要多长时间执行完成。…

Elasticsearch面试系列-01

1. 什么是 Elasticsearch? ES是一种开源、RESTful、可扩展的基于文档的搜索引擎,它构建在Lucene库上。 用户使用Kibana就可以可视化使用数据,同时Kibana也提供交互式的数据状态呈现和数据分析。 Apache Lucene搜索引擎基于JSON文档来进行搜索管理和快速搜索。 Elasticse…

图像分割在疾病诊断中的应用案例

图像分割在疾病诊断中的应用案例&#xff1a; 乳腺癌检测&#xff1a; 利用MRI图像&#xff0c;通过图像分割技术可以将乳腺组织与正常组织区分开来&#xff0c;进而检测出乳腺癌的早期迹象。 皮肤癌诊断&#xff1a; 对于皮肤镜下的图像&#xff0c;应用图像分割技术可以准确…

【双指针】算法例题

目录 二、双指针 25. 验证回文数 ① 26. 判断子序列 ① 27. 两数之和II - 输入有序数组 ② 28. 盛最多水的容器 ② 29. 三数之和 ② 二、双指针 25. 验证回文数 ① 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一…

Day60 (Golang) 单调栈 84.柱状图中最大的矩形

// 84.柱状图中最大的矩形 package mainimport "fmt"func largestRectangleArea(heights []int) int {// 初始化单调栈&#xff08;单调递减栈&#xff09;stack : []int{0}res : 0// 给原数组首位添加0// 数组头部加入0heights append([]int{0}, heights...)// 数组…

【EXPERIMENT】tmux、SCIP

【EXPERIMENT】tmux、SCIP 一、TMUX命令&#xff08;一&#xff09;会话操作&#xff08;二&#xff09;窗口操作&#xff08;三&#xff09;窗格操作 二、SCIP安装 一、TMUX命令 &#xff08;一&#xff09;会话操作 新建会话 tmux new -s name退出会话 ctrl B D查看会话…

C++_第三周做题总结_指针2

id:13 A.月份查询&#xff08;指针数组&#xff09; 题目描述 已知每个月份的英文单词如下&#xff0c;要求创建一个指针数组&#xff0c;数组中的每个指针指向一个月份的英文字符串&#xff0c;要求根据输入的月份数字输出相应的英文单词 1月 January 2月 February 3月 Marc…

行业回暖?这个行业岗位需求飙升6倍!程序员们提前恭喜了!

前言 随着今年史上最长春节假期正式收官&#xff0c;各行各业相继进入开工节奏&#xff0c;就业市场开启持续升温模式。 今年开工首周&#xff0c;人才需求增长明显&#xff0c;求职者活跃度大大增多&#xff0c;就业市场进入了繁忙有序的节奏&#xff0c;呈现出春招市场的勃…

Android获取某个app首次安装时间和更新时间

在Android中&#xff0c;可以使用PackageManager类来获取应用程序的安装时间和上次更新时间。以下是如何实现的一般步骤&#xff1a; 以微信为例&#xff1a; 获取一个PackageManager的实例。使用PackageManager的getPackageInfo方法&#xff0c;传入微信的包名&#xff08;通…

QT网络编程之获取本机网络信息

一.概述 查询一个主机的MAC地址或者IP地址是网络应用中常用到的功能&#xff0c;Qt提供了QHostInfo和QNetworkInterface 类可以用于此类信息的查询 1.QHostInfo 类&#xff08;显示和查找本地的信息&#xff09; 2.QNetworkInterface 类&#xff08;获得应用程序上所在主机的…

Linux性能测试工具整理

性能测试工具&#xff1a;Unixbench lmbench stream iozone fio netperf spec2000 spec2006 一、unixbench unixbench主要是用于系统基础性能测试&#xff0c;unixbench也包含一些非常简单的2D和3D图形测试 UnixBench一个基于系统的基准测试工具&#xff0c;不单纯是CPU 内存 …

在window命令行中,使用conda创建新的虚拟环境时出现的问题以及解决办法

一.出现的问题 C:\Users\zhu>conda create -n ML python3.8 Collecting package metadata (current_repodata.json): failedCondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/win-64/current_repodata.js…

南京大学AI考研,宣布改考408!

官网还没通知 附上南大与同层次学校近四年的分数线对比&#xff0c;整体很难 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 如果确定要冲南大的话建议提早调整自己的复习路线&…

Springboot中使用@Async注解7大失效场景及解决方案

Springboot中使用Async注解7大失效场景及解决方案 前言正文场景一&#xff1a;调用者与被调用者在同一个类中解决方案 场景二&#xff1a;配置类未启用异步支持解决方案 场景三&#xff1a;方法不是 public 的解决方案 场景四&#xff1a;线程池未正确配置解决方案 场景五&…

Combining external-latent attention for medical image segmentation

结合外部潜在注意的医学图像分割 摘要 注意机制是提高医学图像分割性能的新切入点。如何合理分配权重是注意力机制的关键,目前流行的方法包括全局压缩和使用自注意操作的非局部信息交互。然而,这些方法过于关注外部特征,缺乏对潜在特征的开发。全局压缩方法通过全局均值或…

C01 C++ Modding

Modding Programs running on a user-controlled computer are amenable to “modding” . If a piece of information, such as an integer representing health or lives, exists in RAM, one may find and edit it to their liking. Taken to the extreme, entirely new …