StampedLock的理解和使用
StampedLock介绍
StampedLock是为了优化可重入读写锁性能的一个锁实现工具,jdk8开始引入
相比于普通的ReentranReadWriteLock主要多了一种乐观读的功能
在API上增加了stamp的入参和返回值
不支持重入
StampedLock如何使用和使用价值
我看了上面的介绍仍然对StampedLock一头雾水,下面我们来揭开StampedLock神秘的面纱
1、对于悲观读和悲观写的方法与ReentranReadWriteLock读写锁效果一样
下面是StampedLock的悲观读、写锁的实现
static ExecutorService service = Executors.newFixedThreadPool();
static StampedLock lock = new StampedLock();
static long milli = ;
static int count = ;
private static long writeLock() {
long stamp = lock.writeLock(); //获取排他写锁
count+=1;
lock.unlockWrite(stamp); //释放写锁
System.out.println("数据写入完成");
return System.currentTimeMillis();
}
private static void readLock() {//悲观读锁
service.submit(() -> {
int currentCount = ;
long stamp = lock.readLock(); //获取悲观读锁
try {
currentCount = count; //获取变量值
try {
TimeUnit.MILLISECONDS.sleep(milli);//模拟读取需要花费20秒
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
lock.unlockRead(stamp); //释放读锁
}
System.out.println("readLock==" + currentCount); //显示最新的变量值
});
try {
TimeUnit.MILLISECONDS.sleep();//要等一等读锁先获得
} catch (InterruptedException e) {
e.printStackTrace();
}
}
测试一下效果:
public static void main(String[] args) {
long l1 = System.currentTimeMillis();
readLock(); long l2 = writeLock();
System.out.println(l2-l1);
}
因为我对悲观读操作进行了5秒的数据读取延迟,所以写操作要等5秒后读锁释放才能写入数据
输出结果:
数据写入完成的时间比获取读锁晚5043ms
读到的数据仍然是写入前的0
2、对于乐观读(如果没有进入写模式)可以减少一次读锁的性能消耗,并且不会阻塞写入的操作
我们添加了一个乐观读的方法,这个方法仍然模拟读取延迟5秒,乐观读实现需要参考下面的编程模式(获取乐观锁、校验是否进入写模式)
private static void optimisticRead() {
service.submit(() -> {
long stamp = lock.tryOptimisticRead(); //尝试获取乐观读锁
int currentCount = count; //获取变量值
if (!lock.validate(stamp)) { //判断count是否进入写模式
stamp = lock.readLock(); //已经进入写模式,没办法只能老老实实的获取读锁
try {
currentCount = count; //成功获取到读锁,并重新获取最新的变量值
} finally {
lock.unlockRead(stamp); //释放读锁
}
}
try {
TimeUnit.MILLISECONDS.sleep(milli);//模拟读取需要花费20秒
} catch (InterruptedException e) {
e.printStackTrace();
}
//走到这里,说明count还没有被写,那么可以不用加读锁,减少了读锁的开销
System.out.println("optimisticRead==" + currentCount); //显示最新的变量值
});
try {
TimeUnit.MILLISECONDS.sleep();//要等一等读锁先获得
} catch (InterruptedException e) {
e.printStackTrace();
}
}
测试一下效果:
public static void main(String[] args) {
long l1 = System.currentTimeMillis();
optimisticRead();
long l2 = writeLock();
System.out.println(l2-l1);
}
直接看一下输出结果:
数据写入完成的时间比获取读锁晚543ms(说明乐观读并没有阻塞写操作)
5秒后读到的数据仍然是写入前的0
总结
可以看到相比直接用悲观读锁,乐观读锁可以:
1、进入悲观读锁前先看下有没有进入写模式(说白了就是有没有已经获取了悲观写锁)
2、如果其他线程已经获取了悲观写锁,那么就只能老老实实的获取悲观读锁(这种情况相当于退化成了读写锁)
3、如果其他线程没有获取悲观写锁,那么就不用获取悲观读锁了,减少了一次获取悲观读锁的消耗和避免了因为读锁导致写锁阻塞的问题,直接返回读的数据即可(必须再tryOptimisticRead和validate之间获取好数据,否则数据可能会不一致了,试想如果过了validate再获取数据,这时数据可能被修改并且读操作也没有任何保护措施)
StampedLock的理解和使用的更多相关文章
- [JDK8]读写锁的改进:StampedLock
StampedLock是Java8引入的一种新的锁机制,简单的理解,可以认为它是读写锁的一个改进版本,读写锁虽然分离了读和写的功能,使得读与读之间可以完全并发,但是读和写之间依然是冲突的,读锁会完全阻 ...
- Java并发编程笔记之StampedLock锁源码探究
StampedLock是JUC并发包里面JDK1.8版本新增的一个锁,该锁提供了三种模式的读写控制,当调用获取锁的系列函数的时候,会返回一个long 型的变量,该变量被称为戳记(stamp),这个戳记 ...
- Java 8 StampedLock解决同步问题
Java 8新特性探究(十)StampedLock将是解决同步问题的新宠 JDK8中StampedLock原理探究 深入理解StampedLock及其实现原理 JDK1.8 StampedLock源码 ...
- StampedLock
StampedLock是Java8引入的一种新的所机制,简单的理解,可以认为它是读写锁的一个改进版本,读写锁虽然分离了读和写的功能,使得读与读之间可以完全并发,但是读和写之间依然是冲突的,读锁会完全阻 ...
- Java并发(8)- 读写锁中的性能之王:StampedLock
在上一篇<你真的懂ReentrantReadWriteLock吗?>中我给大家留了一个引子,一个更高效同时可以避免写饥饿的读写锁---StampedLock.StampedLock实现了不 ...
- Java8 读写锁的改进:StampedLock(笔记)
StampedLock是Java8引入的一种新的所机制,简单的理解,可以认为它是读写锁的一个改进版本,读写锁虽然分离了读和写的功能,使得读与读之间可以完全并发,但是读和写之间依然是冲突的,读 ...
- 【Java并发工具类】StampedLock:比读写锁更快的锁
前言 ReadWriteLock适用于读多写少的场景,允许多个线程同时读取共享变量.但在读多写少的场景中,还有更快的技术方案.在Java 1.8中, 提供了StampedLock锁,它的性能就比读写锁 ...
- 【漫画】读写锁ReadWriteLock还是不够快?再试试StampedLock!
本文来源于公众号[胖滚猪学编程] 转载请注明出处! 在互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock一文中,我们对比了互斥锁ReentrantLock和读写锁ReadWr ...
- 高并发之Phaser、ReadWriteLock、StampedLock
本系列研究总结高并发下的几种同步锁的使用以及之间的区别,分别是:ReentrantLock.CountDownLatch.CyclicBarrier.Phaser.ReadWriteLock.Stam ...
随机推荐
- linux /proc 接口
无论何时一个硬件中断到达处理器, 一个内部的计数器递增, 提供了一个方法来检查设备 是否如希望地工作. 报告的中断显示在 /proc/interrupts. 下面的快照取自一个双处理 器 Pentiu ...
- ZR 8.31
ZR8.31 题目链接:http://www.zhengruioi.com/contest/388 版权原因,不放题面 A 首先,排序肯定要根据工作经验排序,因为这样便于选择 之后,如果两个人工作经验 ...
- 解决netcore在docker容器中连接oracle报错(timezone region not found)
错误提示: timezone region not found错误原因:docker 容器内时区不是 CST 导致解决办法:1.在dockerfile 中增加一下命令ENV TZ=Asia/Shang ...
- Oracle Net Manager 的使用方法(监听的配置方法)
一,在服务端配置oracle端口 win+R 输入netca 弹出如下窗口后 选择监听程序配置,点击下一步 二.配置端口后使用Telnet工具调试端口是否联通 在命令行输入telnet 服务器ip ...
- Android2_分析项目的结构
一.项目结构 成功运行第一个AS项目HelloWorld之后,我们开始试着分析一下这个项目.毕竟知其然也要知其所以然. 这是一个安卓的项目结构(实际上这是安卓模式的项目结构) 我们可以切换成Proje ...
- phpqrcode生成任意尺寸的二维码
在Thinkphp中整合phpqrcode用于生成二维码,其代码如下: vendor("phpqrcode.phpqrcode"); QRcode::png('http://www ...
- 20191121-8 Scrum立会报告+燃尽图 04
此作业要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/10068 一: 组名:组长组 组长:杨天宇 组员:魏新 罗杨美慧 王歆瑶 ...
- $bzoj4237$稻草人 $cdq$分治
正解:$cdq$分治 解题报告: 传送门$QwQ$ $umm$总感觉做过这题的亚子,,,? 先把坐标离散化,然后把所有点先按$x$排序$QwQ$,然后用类似平面最近点对的方法,先分别解决$mid$两侧 ...
- 洛谷P1002 过河卒 题解 动态规划
题目链接:https://www.luogu.com.cn/problem/P1002 题目大意 棋盘上\(A\)点有一个过河卒,需要走到目标\(B\)点.卒行走的规则:可以向下.或者向右.同时在棋盘 ...
- 组件的props属性和state状态
props属性: 我使用代码来说明React中props属性: // Profile.jsx import React from 'react' ; export default Class Prof ...