本文主要是介绍多线程(31)StampedLock和ReadWriteLock,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
StampedLock
是 Java 8 引入的一种新的锁机制,位于 java.util.concurrent.locks
包下。它可以被认为是 ReadWriteLock
的一个改进版,提供了一种乐观的读锁策略,这种策略可以在某些场景下减少锁的竞争,从而提高性能。与 ReadWriteLock
相比,StampedLock
在使用时需要更加注意,因为它的锁方法不支持重入,并且不支持条件变量。
工作原理
StampedLock
提供了三种主要的访问模式:
-
写锁(Write Lock):
- 类似于
ReadWriteLock
的写锁,提供了排他性的访问。 - 获取写锁时,
StampedLock
会阻塞读锁和写锁的获取。
- 类似于
-
悲观读锁(Pessimistic Read Lock):
- 类似于
ReadWriteLock
的读锁,但在StampedLock
中被称为悲观读锁。 - 当获取到悲观读锁时,写锁的请求会被阻塞,直到所有悲观读锁都释放。
- 类似于
-
乐观读(Optimistic Read):
- 这是
StampedLock
独有的一种读取模式。 - 乐观读不会阻塞写锁的获取,也不会获取实际的锁;它会返回一个邮戳(stamp),代表这次读的版本。
- 在数据实际读取之前,需要检查邮戳,看看在读取过程中有没有写操作进行,如果有,乐观读需要退化为悲观读锁或者重新读取数据。
- 这是
锁的获取和释放
每次锁的获取操作,无论是读锁还是写锁,StampedLock
都会返回一个表示锁状态的邮戳(stamp)。这个邮戳在锁的释放时必须要提供,作为释放锁的凭证。这是一个与 ReadWriteLock
显著不同的特点,因为 ReadWriteLock
并不需要这样的邮戳。
重要特点
-
非阻塞的乐观读:
StampedLock
支持一种非阻塞的读取锁,这可以减少线程阻塞,提高系统吞吐量。 -
不支持条件变量:
StampedLock
不支持条件变量。如果需要类似条件变量的特性,需要使用ReentrantLock
或者ReadWriteLock
。 -
不支持重入:
StampedLock
的锁不支持重入。如果一个线程已经持有锁,它不能再次获取锁,否则可能会导致死锁。 -
中断敏感性:
StampedLock
的锁获取方法提供中断敏感和非中断敏感的版本,这意味着获取锁的操作可以响应中断。 -
锁的转换:
StampedLock
允许从读锁转换为写锁,反之亦然,通过使用特定的方法来尝试转换锁,并检查返回的邮戳是否有效。
示例代码
下面展示了一个使用 StampedLock
的简单示例,包括悲观读锁和写锁的使用:
import java.util.concurrent.locks.StampedLock;public class StampedLockExample {private final StampedLock sl = new StampedLock();// 模拟共享资源private int sharedState;public void write(int newValue) {long stamp = sl.writeLock(); // 获取写锁,并返回邮戳try {sharedState = newValue;} finally {sl.unlockWrite(stamp); // 释放写锁,并提供邮戳}}public int read() {long stamp = sl.readLock(); // 获取悲观读锁,并返回邮戳try {return sharedState;} finally {sl.unlockRead(stamp); // 释放读锁,并提供邮戳}}public int optimisticRead() {long stamp = sl.tryOptimisticRead(); // 尝试获取乐观读,并返回邮戳int currentState = sharedState; // 读取共享资源if (!sl.validate(stamp)) { // 检查在读取过程中是否有写操作stamp = sl.readLock(); // 退化为悲观读锁try {currentState = sharedState;} finally {sl.unlockRead(stamp);}}return currentState;}
}
在这个示例中,我们展示了如何在 StampedLock
中获取和释放写锁和悲观读锁,以及如何执行乐观读取并验证它是否仍然有效。注意:在实际使用中,你需要小心地管理锁的释放,以避免死锁和资源泄露。
这篇关于多线程(31)StampedLock和ReadWriteLock的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!