StampedLock详解
在现代的Java应用中,同步是一个核心问题,尤其是在高并发环境下。Java提供了多种同步机制,从基本的synchronized关键字到更高级的ReentrantLock。但在Java 8中,引入了一个新的同步原语——StampedLock,它旨在提供更高的性能,特别是在读操作远多于写操作的场景中。
1.什么是StampedLock?
StampedLock是一个同步工具,它支持三种访问模式:写锁、乐观读和悲观读。这三种模式使得StampedLock能够在不同的使用场景下提供更高的吞吐量。
StampedLock 是 Java 8 引入的一种新的同步原语,用于替代 ReentrantLock 以提供更高的并发性能。它使用了一种称为 “乐观读”(optimistic reading)的技术,以及 “写锁”(write lock)和 “读锁”(read lock)的分离,以优化读多写少的场景。
2.特点
- 三种访问模式:
- 写锁:独占锁,用于修改数据。
- 乐观读:不阻塞其他读或写,但在数据实际被读取前,会检查锁是否已被其他线程获取。
- 悲观读:阻塞写但不阻塞其他读。
- 优化读操作:在大量读操作和较少写操作的场景中,
StampedLock可以提供更好的性能。 - 不可重入:与
ReentrantLock不同,StampedLock不是可重入的。 - 无条件公平性:
StampedLock不提供任何公平性保证。
3.构造函数和相关方法
- 实例化:
StampedLock lock = new StampedLock();
- 写锁:
long stamp = lock.writeLock();
try {// 修改共享数据的代码
} finally {lock.unlockWrite(stamp);
}
- 乐观读:
long stamp = lock.tryOptimisticRead();
// 读取共享数据的代码
if (!lock.validate(stamp)) {// 如果在读取过程中锁被其他线程获取,则执行以下代码stamp = lock.readLock();try {// 重新读取共享数据的代码} finally {lock.unlockRead(stamp);}
}
- 悲观读:
long stamp = lock.readLock();
try {// 读取共享数据的代码
} finally {lock.unlockRead(stamp);
}
注意事项:
- 由于
StampedLock不可重入,因此在同一个线程中多次获取同一个锁时,必须小心。 StampedLock没有与Condition类似的机制,因此不适合需要等待/通知模式的场景。- 在使用乐观读时,需要注意
validate()方法的调用,以确保在读取过程中锁没有被其他线程获取。
4.为什么选择StampedLock?
与传统的ReentrantLock相比,StampedLock在以下方面提供了优势:
- 性能:
StampedLock通过乐观读和悲观读的分离,优化了读多写少的场景。在大量读操作的场景下,StampedLock可以提供比ReentrantLock更高的吞吐量。 - 灵活性:开发者可以根据具体的使用场景选择合适的锁模式。例如,在数据更新不频繁,但读取非常频繁的场景下,乐观读可能是一个更好的选择。
5.使用示例
首先是Counter类,它使用StampedLock来保护其内部计数器:
import java.util.concurrent.locks.StampedLock;public class Counter {private int count;private final StampedLock lock = new StampedLock();public void increment() {long stamp = lock.writeLock();try {count++;} finally {lock.unlockWrite(stamp);}}public int read() {long stamp = lock.readLock();try {return count;} finally {lock.unlockRead(stamp);}}public int optimisticRead() {long stamp = lock.tryOptimisticRead();int currentCount = count;// 检查在读取过程中是否有写操作if (!lock.validate(stamp)) {// 如果写锁已被获取,则升级为悲观读锁stamp = lock.readLock();try {currentCount = count;} finally {lock.unlockRead(stamp);}}return currentCount;}
}
接下来是测试类CounterTest,它将创建多个线程来模拟并发读写操作:
public class CounterTest {public static void main(String[] args) throws InterruptedException {final Counter counter = new Counter();// 创建并启动写线程Thread writer = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});// 创建并启动读线程Thread reader = new Thread(() -> {int sum = 0;for (int i = 0; i < 1000; i++) {sum += counter.read();}System.out.println("Sum read via pessimistic lock: " + sum);});// 创建并启动乐观读线程Thread optimisticReader = new Thread(() -> {int optimisticSum = 0;for (int i = 0; i < 1000; i++) {optimisticSum += counter.optimisticRead();}System.out.println("Sum read via optimistic lock: " + optimisticSum);});// 启动所有线程writer.start();reader.start();optimisticReader.start();// 等待所有线程完成writer.join();reader.join();optimisticReader.join();// 打印最终计数器的值System.out.println("Final counter value: " + counter.read());}
}
运行结果:
Sum read via pessimistic lock: 999000
Sum read via optimistic lock: 990000
Final counter value: 1000
在这个例子中,pessimistic lock(悲观锁)指的是使用readLock方法获取的读锁,它保证在读取计数器时不会被写线程中断。而optimistic lock(乐观锁)则尝试在不阻塞的情况下读取计数器,但如果在读取过程中发生了写操作,则会重新读取。
由于乐观读不保证每次都能成功,所以在高并发环境下,乐观读计算的和可能会小于实际写入的次数。然而,在读多写少且写冲突不频繁的场景下,乐观读通常能够提供更高的吞吐量。
6.总结
StampedLock是一个强大的同步工具,它在特定的使用场景下可以提供比传统锁更高的性能。
相关文章:
StampedLock详解
在现代的Java应用中,同步是一个核心问题,尤其是在高并发环境下。Java提供了多种同步机制,从基本的synchronized关键字到更高级的ReentrantLock。但在Java 8中,引入了一个新的同步原语——StampedLock,它旨在提供更高的…...
Linux中DCHP与时间同步
目录 一、DHCP (一)工作原理 1.获取 2.续约 (二)分配方式 (三)服务器配置 1.随机地址分配 2.固定地址分配 二、时间同步 (一)ntpdate (二)chrony …...
国产系统-银河麒麟桌面版V10安装字体-wps安装字体
安装系统:银河麒麟V10 demodemo-pc:~/桌面$ cat /proc/version Linux version 5.10.0-8-generic (builddfa379600e539) (gcc (Ubuntu 9.4.0-1kylin1~20.04.1) 9.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #33~v10pro-KYLINOS SMP Wed Mar 22 07:21:49 UTC 20230.系统缺失…...
python 10常用自动化脚本收藏好
01、 图片优化器 使用这个很棒的自动化脚本,可以帮助把图像处理的更好,你可以像在 Photoshop 中一样编辑它们。 该脚本使用流行的是 Pillow 模块 # Image Optimizing # pip install Pillow import PIL # Croping im PIL.Image.open("Image1.jp…...
java物品检验管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 java Web 物品检验管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysq…...
Pandas实战100例 | 案例 2: 数据探索 - 查看和理解数据
案例 2: 数据探索 - 查看和理解数据 知识点讲解 在数据分析的早期阶段,对数据进行初步的探索是非常重要的。这包括查看数据的基本信息、统计摘要、以及数据的形状。 示例代码 查看数据的基本信息 # 显示 DataFrame 的基本信息,包括列名、非空值数量…...
c++qt-基本组件
1. Designer 设计师(掌握) Qt包含了一个Designer程序,用于通过可视化界面设计开发界面,保存的文件格式为.ui(界面文件)。界面文件内部使用xml语法的标签式语言。 在Qt Creator中创建项目时,选中…...
SpringBoot多环境配置Maven Profile组
Maven profile组 注意切换配置时 mvn clean下 或者 clean 加install 或者compile 编译 clean之后 install下 或者compile 编译 nohup java -Xms256m -Xmx512m -Dfile.encodingUTF-8 -jar demo.jar --spring.profiles.activeprod > system.log 2>&1 &...
服务器配置 ssh 密钥登录
服务器配置 ssh 密钥登录 配置 服务器安全组策略,开放 ssh 22 端口,以 root 用户登录服务器。 配置 ssh key 登录 ssh-keygen 生成公钥和私钥对 如果不需要其他设置,一直回车 可以在 ~/.ssh 目录下看到两个文件,即刚生成的私钥…...
使用递归将list转换成tree
在产品研发时遇到这样一个问题,对于省市区县这类三级联动的数据,前端插件需要一次把数据全部返回,单纯的使用接口查询字节的没办法满足要求。 如果一次把数据全部返回,前端使用起来很麻烦需要一条一条的进行查找。 常规的使用方…...
untiy使用http下载资源
文章目录 提醒下载一个资源并保存到本地下载一张图片 提醒 部分API需要将Unity的 Edit/PrejectSetting/Player/OtherSetttings/AConfiguration/ApiCompatibilityLevel 设为.NetFramework 才可以使用 下载一个资源并保存到本地 private IEnumerator DownloadFormServer_IE(st…...
03-编码篇-x264编译与介绍
使用FFMPEG作编码操作时,会涉及到将yuv数据编码成h264数据,FFmpeg的libavcodec中的libx264.c会调用x264库的源码作编码: 1.x264库编译 下载X264,地址为:http://www.videolan.org/developers/x264.html,并解…...
生活自来水厂污水处理设备需要哪些
生活自来水厂是确保我们日常用水质量安全的重要设施。在自来水的生产过程中,污水处理设备是不可或缺的环节。那么,生活自来水厂的污水处理设备都有哪些呢?本文将为您详细介绍。 首先,生活自来水厂的污水处理设备主要包括预处理设备…...
Full names for abbreviations of Linux Commands
synopsis Towards/On Full names for abbreviations of Linux Commands I) website addressII) Mapping between full names and abbreviations I) website address II) Mapping between full names and abbreviations su:Swith user 切换用户,切换到ro…...
kafka下载安装部署
Apache kafka 是一个分布式的基于push-subscribe的消息系统,它具备快速、可扩展、可持久化的特点。它现在是Apache旗下的一个开源系统,作为hadoop生态系统的一部分,被各种商业公司广泛应用。它的最大的特性就是可以实时的处理大量数据以满足各…...
python包管理工具:pipenv的基本使用
很多语言都提供了环境隔离的支持,例如nodejs的node_module,golang的go mod,python也有virtualenv和pyvenv等机制。 为了建立依赖快照,通常会用pip freeze > requirements.txt 命令生成一个requirements.txt文件,在…...
AI系统ChatGPT网站系统源码AI绘画详细搭建部署教程,支持GPT语音对话+DALL-E3文生图+GPT-4多模态模型识图理解
一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Ch…...
MC-4/11/03/400步进电机驱动器的主要驱动方式有哪些?
MC-4/11/03/400步进电机驱动器的主要驱动方式有哪些? 步进电机驱动器是一种将电脉冲转化为角位移的执行机构。当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,这个固定的角度被称为“步距角”。步进电机不能…...
大数据技术原理与应用期末复习(林子雨)
大数据技术原理与应用期末复习(林子雨) Hadoop的特性HBase编程实践NoSQL的四大类型键值数据库优点:缺点: 列族数据库优点:缺点: 文档数据库优点:缺点: 图数据库优点:缺点…...
C练习——魔术师猜三位数
题目: 有一种室内互动游戏,魔术师要每位观众心里想一个三位数abc(a、b、c分别是百位、十位和个位数字),然后魔术师让观众心中记下acb、bac、bca、cab、cba五个数以及这5个数的和值。只要观众说出这个和是多少…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
