共计 2072 个字符,预计需要花费 6 分钟才能阅读完成。
前言
在理解完 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 并没有什么关系,它是在本人外部保护了一个双向阻塞队列。