使用读写锁提高并发
我们想要的是:允许多个线程同时读,但只要有一个线程在写,其他线程就必须等待。
ReadWriteLock
ReadWriteLock的作用:
- 只允许一个线程写入(其他线程既不能写入也不能读取);
- 没有写入时,多个线程允许同时读(提高性能)。
- 如何声明读写锁:
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();private final Lock readLock = lock.readLock();private final Lock writeLock = lock.writeLock();
运行下面的代码发现:
读写锁并发的时候,读的数据并不是写入的终态数据

package org.meituan.javalearn.thread;import lombok.SneakyThrows;import java.util.LinkedList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;/*** @projectName: codebetter* @package: org.meituan.javalearn.thread* @className: ReadWriteQueue* @author: fangjiayueyuan* @description: TODO* @date: 2023/5/8 下午10:01* @version: 1.0*/
public class ReadWriteQueue {public static void main(String[] args) throws InterruptedException {LinkedList<Thread> threadPools = new LinkedList<Thread>();final ReadWriteTaskQueue taskQueue = new ReadWriteTaskQueue();for(int i=0;i<199995;i++){threadPools.add(new Thread(new Runnable() {@SneakyThrows@Overridepublic void run() {System.out.println(taskQueue.getTask());}}));}Thread addThread = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 1005; i++) {taskQueue.addTask("The"+i+"th task to be closed");}}});addThread.start(); // 读写锁无法进行wait和notify???for(Thread thread:threadPools){thread.start();}}
}
class ReadWriteTaskQueue{private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();private final Lock readLock = lock.readLock();private final Lock writeLock = lock.writeLock();LinkedList<String> taskQueue = new LinkedList<String>();public void addTask(String task){writeLock.lock();try{taskQueue.add(task);}finally {writeLock.unlock();}}public Integer getTask() throws InterruptedException {readLock.lock();try{while(taskQueue.isEmpty()){return 0;}return taskQueue.size();}finally {readLock.unlock();}}}
最初,写了一个类:ReadWriteTaskQueue,如下所示。队列可以实现增加任务和读取任务并打印的功能。但实际上,这个类实际上两个功能都在写,不是读写锁的应用场景。
package org.meituan.javalearn.thread;
import lombok.SneakyThrows;
import java.util.LinkedList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;/*** @projectName: codebetter* @package: org.meituan.javalearn.thread* @className: ReadWriteQueue* @author: fangjiayueyuan* @description: TODO* @date: 2023/5/8 下午10:01* @version: 1.0*/
public class ReadWriteQueue {public static void main(String[] args) throws InterruptedException {LinkedList<Thread> threadPools = new LinkedList<Thread>();final ReadWriteTaskQueue taskQueue = new ReadWriteTaskQueue();for(int i=0;i<15;i++){threadPools.add(new Thread(new Runnable() {@SneakyThrows@Overridepublic void run() {System.out.println(taskQueue.getTask());}}));}Thread addThread = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 5; i++) {taskQueue.addTask("The"+i+"th task to be closed");}}});addThread.start(); // 读写锁无法进行wait和notify???for(Thread thread:threadPools){thread.start();}}
}
class ReadWriteTaskQueue{private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();private final Lock readLock = lock.readLock();private final Lock writeLock = lock.writeLock();LinkedList<String> taskQueue = new LinkedList<String>();public void addTask(String task){writeLock.lock();try{taskQueue.add(task);}finally {writeLock.unlock();}}public String getTask() throws InterruptedException {readLock.lock();try{while(taskQueue.isEmpty()){return "None";}return taskQueue.remove();}finally {readLock.unlock();}}
}

注意:ReadWriteLock看起来无法实现线程的协调,如果需要做类似于发布-订阅这种模式的消息队列,则需要通过Condition实现wait和notify来达到多线程协调的目的。
总结:
- 使用ReadWriteLock可以提高读取效率:
– ReadWriteLock只允许一个线程写入;
– ReadWriteLock允许多个线程在没有写入时同时读取;
– ReadWriteLock适合读多写少的场景。 - 缺点:
如果有线程正在读,写线程需要等待读线程释放锁后才能获取写锁,即读的过程中不允许写,这是一种悲观的读锁。
StampedLock
乐观锁的意思就是乐观地估计读的过程中大概率不会有写入,因此被称为乐观锁。悲观锁就是在读的过程中拒绝写入,显然乐观锁的并发效率更高。但有可能造成读写不一致。因此需要增加一些代码来判断读的状态。
声明StampedLock:private final StampedLock lock = new StampedLock;
读锁,需要判断读的时候有没有写入,通过盖得“章”Stamp来判断:
long stamp = lock.tryOptimisticRead();// 先尝试使用乐观锁
if(!validate(stamp)) // 通过Stamp来判断,顾名思义StampedLock 已经盖过章的lock
stamp = lock.readLock(); // 如果在读的时候进行了写入,则需要悲观锁来读一遍 由于大概率读的时候不会写,所以大概率都是走的乐观锁,因此能提高并发
lock.unlockRead(stamp);// 记得关闭读锁
写锁:
long stamp = lock.writeLock(); // 上写锁
lock.unlockWrite(stamp); // 关闭写锁
使用StampedLock对上面的ReadWriteTaskQueue进行改造如下:
class ReadWriteTaskQueue{private final StampedLock lock = new StampedLock();LinkedList<String> taskQueue = new LinkedList<String>();public void addTask(String task){ // 写锁long stamp = lock.writeLock();try{taskQueue.add(task);}finally {lock.unlockWrite(stamp);}}public Integer getTask() throws InterruptedException {long stamp = lock.tryOptimisticRead();if(!lock.validate(stamp)){try{stamp = lock.readLock();while(taskQueue.isEmpty()){return 0;}return taskQueue.size();}finally {lock.unlockRead(stamp);}}return taskQueue.size();}
}相关文章:
使用读写锁提高并发
我们想要的是:允许多个线程同时读,但只要有一个线程在写,其他线程就必须等待。 ReadWriteLock ReadWriteLock的作用: 只允许一个线程写入(其他线程既不能写入也不能读取);没有写入时…...
使用@PropertySource加载配置文件
1.PropertySource和PropertySources注解 1.1.PropertySource注解概述 PropertySource注解是Spring 3.1开始引入的配置类注解。通过**PropertySource注解可以将properties配置文件中的key/value存储到Spring的Environment中,Environment接口提供了方法去读取配置文…...
事务及分布式事务解决方案
基础概念 1.1.事务 事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败。 1.2.本地事务 在计算机系统中,更多的是通过关系型数据库来控制事务,利用数据库本身的事务特性来实现&a…...
【思科、华为、华三、锐捷网络设备巡检命令】
华三 screen-1ength disable 取消分页 displayversion 查看版本 displayclock 查看日期时钟 displayfan 查看风扇状态 displaypower 查看电源信息 displaycpu-usage 查看CPU利用率 displaymemory 查看内存利用率 display environment 查看温度信息 display device 查看设备信息…...
代码随想录算法训练营第五十二天
代码随想录算法训练营第五十二天| 300.最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组 300.最长递增子序列674. 最长连续递增序列718. 最长重复子数组 300.最长递增子序列 题目链接:最长递增子序列 这里是不用处理if nums[i] &l…...
【Linux网络】传输层中UDP和TCP协议
文章目录 1、再谈端口号2、UDP协议3、TCP协议3.1 TCP协议段格式3.2 TCP的三次握手和四次挥手(连接管理机制)3.3 TCP的滑动窗口3.4 TCP的流量控制3.5 拥塞控制3.6 延迟应答和捎带应答3.7 面向字节流和粘包问题3.8 TCP总结 1、再谈端口号 端口号port标识一…...
工具︱ Web3加密浏览器Brave有什么特别之处?
使用浏览器来上网访问和获取各种信息和资源已经成为传统互联网民的普遍活动,下一代互联网协议Web3的核心特点是去中心化,即不依赖于中心化的服务器和数据中心,而是通过分布式的网络节点来实现数据存储和传输。 浏览器承载着信息网络与用户需求…...
绝对不能错过这份沃尔玛实用插件工具大全
龙哥最近发现很多跨境卖家都比较少运营沃尔玛这个平台。沃尔玛除了是世界500强之外,它的线上商城也弄得很好。它的电商平台主要是售卖自营的,然后你也可以入驻来卖自己的产品,就像是我们国内的京东一样。今天龙哥就给大家分享一些沃尔玛专用插…...
【Java】字符串模板拼接的方法
引 在Java中,构建字符串是非常常见的操作。在很多时候,我们都需要使用变量或输入来定制一个文本输出,例如打印日志、生成HTML代码或构建错误消息。而当需要进行字符串连接时,字符串模板是一种常用的方法。在本篇博客中࿰…...
Vue3项目中使用ECharts图表并实现自适应效果
文章目录 一、Vue3项目安装ECharts二、引入、使用ECharts1.创建图表组件,并在父组件中引入使用2.引入ECharts3.ECharts图表自适应 总结 一、Vue3项目安装ECharts 在项目中输入如下代码: npm install echarts --save安装完成可以在package.json中看到&a…...
快速跑通环信IM Android Demo
1、以Android 4.0.0 Demo为例 https://www.easemob.com/download/demo (下载别的版本的demo 可以修改版本号直接下载就就可以) https://downloadsdk.easemob.com/downloads/easemob-sdk-4.0.0.zip 运行时遇到以下报错在项目build.gradle中添加运行时遇…...
leetcode解题思路分析(一百三十九)1190 - 1196 题
反转每对括号间的子串 给出一个字符串 s(仅含有小写英文字母和括号)。请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。注意,您的结果中 不应 包含任何括号。 可以简单的用栈保存当前层…...
PHP+vue基于web的小区物业管理管理系统1995a
小区物业管理系统主要是对小区物业以及居民信息进行管理,方便用户使用该资源的一种有效手段。能有效地对物业以及用户信息进行管理并为广大用户服务是该管理系统的基本要求,同时用户也可以及时了解最新的物业信息,方便地查询相关物业情况。基…...
区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测
区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测…...
【AI 导航网站】为了更好的收集 AI 资源,我开发了一个 AI 导航网站
AI 导航网站 目前 AI 应用正呈迸发式增长,然而一个人获取资源的途径有限,对于目前存在的AI工具不能很好的收集总结,所以基于此,我开发了这个一个AI导航网站,希望通过它,收集出目前存在的热门的AI应用&…...
谈谈HMI 的自动化生成技术
人机界面(HMI)是自动化领域不可或缺重要组成部分。尽管人机界面系统的设计看上去并没有太大的技术门槛,但是设计一个HMI系统的工作量是巨大的。如果你没有足够的耐心便完成不了一个通用的HMI系统。构建UI控件库是一个似乎永远完不成的事情&am…...
docker安装elasticsearch
使用docker部署 部署elasticsearch # 拉取镜像 docker pull elasticsearch# 创建容器 docker run --name es -p 9200:9200 \-p 9300:9300 \-e "discovery.typesingle-node" \-e ES_JAVA_OPTS"-Xms64m -Xmx128m" \-v /home/es/conf/elasticsearch.yml:/…...
Docker:使用dockerFile创建镜像(war包和jar包)
1、使用war包打镜像 (1)在war的当前路径下,新建一个文件——Dockerfile (2)编辑Dockerfile文件 vim Dockerfile Dockerfile文件内容: FROM java:8 # 选择项目中要求的版本 MAINTAINER ylb …...
2.基础篇
目录 一、描述软件测试的生命周期(软件测试的流程) 二、如何描述一个bug 三、bug的级别(粗略划分) 四、bug的生命周期 五、因为一个bug和开发人员产生争执怎么办 六、如何设置弱网? 一、描述软件测试的生命周期&a…...
取代你的可能不是AI,而是比你更会使用AI的人
1、背景 从开始了解AI到现在已经1个月了,最明显的就是,产品层出不穷,以前只有技术人员才关系AI,现在各行各业都在关系AI,都希望通过它提高生产力和创造力; 在当今大数据和人工智能时代,职场和企…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
