StampedLock接口是Java 8中引入的一种读写锁机制。它提供了一种乐观读取和悲观读/写锁的实现方式。
与传统的读写锁(如ReentrantReadWriteLock)相比,StampedLock具有更高的并发性能和灵活性。它适用于读操作非常频繁而写操作较少的场景。
下面是StampedLock接口的几个主要方法:
- long readLock(): 获取一个悲观读锁,并返回一个标记值(stamp),如果没有其他线程持有写锁,则立即返回;否则会阻塞等待。
- long tryReadLock(): 尝试获取一个悲观读锁,如果成功则返回一个标记值,如果失败则立即返回0,不会阻塞。
- void unlockRead(long stamp): 释放一个悲观读锁。
- long writeLock(): 获取一个写锁,并返回一个标记值,如果没有其他线程持有读锁或写锁,则立即返回;否则会阻塞等待。
- long tryWriteLock(): 尝试获取一个写锁,如果成功则返回一个标记值,如果失败则立即返回0,不会阻塞。
- void unlockWrite(long stamp): 释放一个写锁。
- long tryOptimisticRead(): 尝试获取一个乐观读锁,返回一个标记值,不会阻塞。乐观读锁不提供线程安全性保证,需要结合验证操作来确保数据的一致性。
- boolean validate(long stamp): 验证标记值对应的锁是否仍然有效。
使用StampedLock时需要注意以下几点:
- 你可以同时拥有一个悲观读锁和一个写锁,但不能同时拥有多个写锁。
- 在使用乐观读锁后,需要通过调用validate()方法来验证标记值是否仍然有效,并且在验证失败时重新获取悲观读锁或写锁。
- StampedLock是非重入锁,即同一个线程在持有锁的情况下再次请求该锁会导致死锁。
这里是一个简单示例代码,演示了如何使用StampedLock实现读写锁:
import java.util.concurrent.locks.StampedLock;
public class StampedLockExample {
private double x, y;
private final StampedLock lock = new StampedLock();
public void write(double newX, double newY) {
long stamp = lock.writeLock();
try {
x = newX;
y = newY;
} finally {
lock.unlockWrite(stamp);
}
}
public double read() {
long stamp = lock.tryOptimisticRead();
double currentX = x;
double currentY = y;
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
currentX = x;
currentY = y;
} finally {
lock.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
}
在上面的示例中,write()
方法使用写锁来更新x和y的值,而read()
方法则使用乐观读锁(如果验证失败,则转为悲观读锁)来读取x
和y
的值,并计算其平方和。