使用读写锁提高并发
我们想要的是:允许多个线程同时读,但只要有一个线程在写,其他线程就必须等待。
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,都希望通过它提高生产力和创造力; 在当今大数据和人工智能时代,职场和企…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...
