StampedLock(印戳锁)详解
文章目录
- 1. 简介
- 2. 代码示例
1. 简介
StampedLock(印戳锁)是对ReentrantReadWriteLock读写锁的一种改进,主要的改进为:在没有写只有读的场景下,StampedLock支持不用加读锁而是直接进行读操作,最大程度提升读的效率,只有在发生过写操作之后,再加读锁才能进行读操作
StampedLock有以下3种模式:
- 悲观读锁:与ReadWriteLock的读锁类似(这里的读锁不可重入),多个线程可以同时获取悲观读锁,悲观读锁是一个共享锁。
- 乐观读锁:相当于直接操作数据,不加任何锁,连读锁都不要。在操作数据前并没有通过CAS 设置锁的状态,仅仅通过位运算测试。如果当前没有线程持有写锁 ,则简单地返回 一个非 0 的 stamp 版本信息 ,返回0则说明有线程持有写锁。 获取该 stamp 后在具体操作数据前还需要调用validate 方法验证该 s tamp 是否己经不可用
- 写锁:与ReadWriteLock的写锁类似,写锁和悲观读锁是互斥的。虽然写锁与乐观读锁不会互斥,但是在数据被更新之后,之前通过乐观读锁获得的数据已经变成了脏数据。是 一 个排它锁或者独占锁,某时只有 一 个线程可以获取该锁,当二个线程获取该锁后,其他请求读锁和写锁的线程必须 等待 ,这类似于ReentrantReadWriteLock 的写锁(不同点在于这里的写锁不可重入)
StampedLock 的读写锁都是不可重入锁,所以在获取锁后释放锁前不应该再调用会获取锁的操作,以避免造成调用线程被阻塞
2. 代码示例
package innerlock;import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.locks.StampedLock;public class StampedLockTest {//创建1个map 代表共享数据final static HashMap<String, String> MAP=new HashMap<>();//创建一个印戳锁final static StampedLock STAMPED_LOCK=new StampedLock();/** 对共享数据的写操作*/public static Object put(String key,String value) {long stamp=STAMPED_LOCK.writeLock();try {System.out.println(getNowTime()+": 抢占了写锁,开始写操作");String put=MAP.put(key, value);return put;} catch (Exception e) {e.printStackTrace();}finally {System.out.println(getNowTime()+": 释放了写锁");STAMPED_LOCK.unlock(stamp);}return null;}/** 对共享数据的悲观读操作*/public static Object pessimisticRead(String key) {System.out.println(getNowTime()+": 进入过写模式,只能悲观读");long stamp=STAMPED_LOCK.readLock();try {System.out.println(getNowTime()+": 获取了读锁");String value=MAP.get(key);return value;} finally {System.out.println(getNowTime()+": 释放了读锁");STAMPED_LOCK.unlockRead(stamp);}}/** 对共享数据的乐观读操作*/public static Object optimisticRead(String key) {String value=null;long stamp=STAMPED_LOCK.tryOptimisticRead();if(stamp!=0) {System.out.println(getNowTime()+": 乐观锁的印戳值获取成功");value=MAP.get(key);}else if (stamp==0) { //代码1System.out.println(getNowTime()+": 乐观锁的印戳值获取失败,开始使用悲观读");return pessimisticRead(key);}if(!STAMPED_LOCK.validate(stamp)) {//代码2处System.out.println(getNowTime()+": 乐观读的印戳值已经过期");return pessimisticRead(key);}else {System.out.println(getNowTime()+": 乐观读的印戳值没有过期");return value;}}public static Date getNowTime() {return new Date();}public static void main(String[] args) throws InterruptedException {MAP.put("initKey", "initValue");Thread t1=new Thread(()->{System.out.println(optimisticRead("initKey"));},"读线程1");Thread t2=new Thread(()->{put("key1", "value1");},"写线程1");Thread t3=new Thread(()->{System.out.println(optimisticRead("initKey"));},"读线程2");t1.start();t1.join();t2.start();t3.start();Thread.sleep(1000);}}
- 代码1处stamp==0说明当前为写锁模式,只能使用悲观读
- 代码2处: 乐观读已经过了一段时间,期间可能发生写入,所以验证乐观读的印戳值是否有效,即判断LOCK是否进入过写模式
StampedLock(印戳锁)详解相关推荐
- 多线程锁详解之【临界区】
更多的锁介绍可以先看看这篇文章:多线程锁详解之[序章] 正文: 一般锁的类型可分为两种:用户态锁和内核态锁.用户态锁是指这个锁的不能够跨进程使用.而内核态锁就是指能够跨进程使用的锁.一般书中会说,wi ...
- mysql默认使用悲观锁_mysql乐观锁和悲观锁详解
mysql乐观锁和悲观锁详解 相信很多朋友在面试的时候,都会被问到乐观锁和悲观锁的问题,如果不清楚其概念和用法的情况下,相信很多朋友都会感觉很懵逼,那么面试的结果也就不言而喻了. 那么乐观锁和悲观锁到 ...
- 可重入锁详解(什么是可重入)
可重入锁详解 概述 什么是 "可重入",可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁.例如 package com.test.reen;// 演示可重入锁是什么 ...
- 公平锁非公平锁的实际使用_java 线程公平锁与非公平锁详解及实例代码
java 线程公平锁与非公平锁详解 在ReentrantLock中很明显可以看到其中同步包括两种,分别是公平的FairSync和非公平的NonfairSync.公平锁的作用就是严格按照线程启动的顺序来 ...
- python gil 解除_详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案
先看一道GIL面试题: 描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因. GIL:又叫全局解 ...
- Redis分布式锁详解
Redis分布式锁详解 1. 分布式所概述 1.1 分布式锁 2. 缓存数据库Redis 2.1 redis简介 2.2 Springboot整合Redis两种方式 3. 实现验证 3.1 环境准备 ...
- Redis缓存雪崩、穿透、击穿,布隆过滤器,分布式锁详解
缓存雪崩 在某一个时间存在大量的缓存key失效 解决办法 1.有效期一直---->给每一个数据加上水机有效期 2.redis挂掉了----->使用redis集群,分摊key的存储 引出re ...
- 旋转矩阵、欧拉角、万向锁详解
旋转矩阵.欧拉角.万向锁详解 一:物体的姿态描述 物体的姿态可由固定于此物体的坐标系描述,为了规定空间某刚体B的姿态,设置一直角坐标系{B}与此刚体固接.用坐标系{B}的三个单位主矢量{Xb,Yb,Z ...
- Java锁详解:“独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁+线程锁”
在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类: 公平锁/非公平锁 可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 自旋锁 线程锁 乐观锁 VS 悲 ...
- 最全Java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁
在Java并发场景中,会涉及到各种各样的锁,比如:高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景,这些锁有对应的种类:公平锁,乐观锁,悲观锁等等,这篇文章来详细介绍各种锁的分类: 公 ...
最新文章
- 各计算机语言之父,四大编程语言之父
- Caffe2——cifar10数据集创建lmdb或leveldb类型的数据
- 天气预报开放API调用
- java第二阶段_Java第二阶段总结
- Linux下jdk配置环境变量
- MYSQL-创建存储过程
- Computer Vision News
- 关于阿里云OSS报错-java.lang.ClassNotFoundException: org.jdom.input.JDOMParseException
- list集合排序_Java面试第七部分 Java的集合
- matplotlib绘图基础
- 重置winsock目录
- matlab画图常用函数image、imagesc、imshow区别
- 创业者2012必看十大文章(10)
- 2021年全球与中国颅骨稳定系统行业市场规模及发展前景分析
- 取消键盘Fn功能键方式
- Go Module使用 六大场景讲解示例
- ENSP的AR40问题解决
- 3.7版本逆向微信实现多开
- 渗透测试学习计划路线思维导图v1.0
- 4.怎么理解相互独立事件?真的是没有任何关系的事件吗? 《zobol的考研概率论教程》
热门文章
- 图解迷宫算法(广度优先遍历)
- excel能和html链接吗,excel中怎么设置超链接并且整个excel表格发给别人时超链接还是能用...
- 经纬度坐标转换xy坐标 python_Python 高斯坐标转经纬度算法
- 计算机操作入门基础知识,电脑入门基本操作知识
- android packagemanager源码,Android源码个个击破之PackageManager
- getParameterValues使用
- 电脑写作与发布哪款软件好?
- mysql的pdb文件在哪里_pdb是什么文件?pdb数据库文件怎么打开?
- 机械工程c语言第一学期考试题,科学出版社机械工程图学习题集1~10章答案.ppt
- windows server2008 安装iscsi服务