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个数的和值。只要观众说出这个和是多少…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
