前言
在理解完 ReentrantLock 和 ReentrantReadWriteLock 之后,惊奇的发现 JUC 下还有一个 StampedLock 。 查阅材料发现是 JDK8 新增的一个锁。当初曾经 JDK15 了,原谅我的见多识广,切实是业务开发中用的太少。那行吧,连忙来看一下 StampedLock 到底是什么?为什么有了 ReentrantLock 和 ReentrantReadWriteLock 之后还要设计一个 StampedLock ?
公众号:『 刘志航 』,记录工作学习中的技术、开发及源码笔记;时不时分享一些生存中的见闻感悟。欢送大佬来领导!
介绍
往期回顾
在介绍 StampedLock 之前还是先看一下 ReentrantLock 和 ReentrantReadWriteLock。
ReentrantLock:互斥锁,同时只有一个线程能够持有。反对锁重入。
ReentrantReadWriteLock:读写锁,分为读锁和写锁,反对重入。其中读读共享,写写独占,读写互斥,写读互斥。反对锁降级,线程获取写锁后能够降级为读锁。适宜读多写少的场景。
那为什么要设计 StampedLock 呢?先来看一下源码上的正文:
StampedLock
基于性能的锁,具备三种模式来管制读/写访问。StampedLock的状态由版本和模式组成。锁获取办法返回一个 stamp 用来示意并管制锁状态的拜访;这些办法的“try”版本可能会返回非凡值零,以示意无奈获取拜访权限。
锁的开释和转换方法须要应用 stamp 作为参数,如果它们与锁的状态不匹配,则会失败。
三种模式是:写锁、读锁、乐观读锁。
并且具备以下特色:
- 获取锁的时候(无论读锁还是写锁或者乐观读锁)都会返回一个 stamp,在开释锁的时候须要应用这个 stamp;
- 反对三种模式转换;
- 不是可重入的,所以取得锁的时候,不要尝试再次获取。
应用样例
/** * @author liuzhihang * @date 2020/8/6 15:27 */public class Count { private int num; private final StampedLock stampedLock = new StampedLock(); // 应用写锁,在对 num 进行写入的时候加锁 void write(int x) { long stamp = stampedLock.writeLock(); try { num += x; } finally { stampedLock.unlockWrite(stamp); } } // 乐观读 int read() { // 获取乐观读锁;返回 stamp long stamp = stampedLock.tryOptimisticRead(); try { // validate 验证是否被写锁持有 // 没有被写锁持有,能够间接返回 if (!stampedLock.validate(stamp)) { // 被写锁持有,那只能获取读锁 stamp = stampedLock.readLock(); } return num; } finally { stampedLock.unlockRead(stamp); } } void convertWrite(int x) { // 读 long stamp = stampedLock.readLock(); try { while (num == x) { // 满足条件,转换为写锁 long ws = stampedLock.tryConvertToWriteLock(stamp); // 转为写锁胜利 if (ws != 0L) { stamp = ws; num = x; break; } else { // 转换失败,开释读锁 stampedLock.unlockRead(stamp); // 再次获取写锁 stamp = stampedLock.writeLock(); } } } finally { stampedLock.unlock(stamp); } }}
- 写锁应用办法一样;
- 乐观读,能够先去读数据,发现没有扭转能够返回,发现扭转了,则从新获取读锁,而后再返回;
- 读锁能够降级为写锁,通过 tryConvertToWriteLock 办法。
总结
UML
通过 UML 能够看出 StampedLock 和 AQS 并无任何关系。
StampedLock 和 ReentrantReadWriteLock 的区别?
- StampedLock 也是读写锁,然而和 AQS 没有关系
- StampedLock 除了 读锁和写锁,还有一个乐观读。
- StampedLock 的读锁能够降级为写锁。
- StampedLock 不反对锁重入。
小结
本文次要介绍 StampedLock 的相干应用及和 ReentrantReadWriteLock 的区别。
因为工作的确很少应用,浏览源码,外部自旋逻辑等有很多。如果介绍的话会篇幅特地长,这里就省略了。有趣味的小伙伴能够本人浏览源码。
因为 StampedLock 提供的乐观读锁反对,所以在多线程多读状况下,性能比 ReentrantReadWriteLock 要更好,然而须要留神的是 StampedLock 是不反对锁重入的。
另一个须要记住的就是 StampedLock 和 AQS 并没有什么关系,它是在本人外部保护了一个双向阻塞队列。