StampedLock
StampedLock是比ReadWriteLock效率更高的读写锁
StampedLock支持写锁,悲观读锁和乐观读
- 悲观读锁
StampedLock lock = new StampedLock();
long rStamp = lock.readLock();
try {
...
} finally {
lock.unlockRead(rStamp);
}
- 写锁
long wStamp = lock.writeLock();
try {
...
} finally {
lock.unlockWrite(wStamp);
}
- 乐观读
//乐观读
long optimistic = lock.tryOptimisticRead();
// 共享变量操作
...
// 乐观读验证是否成功
if (!lock.validate(optimistic)) {
// 共享变量操作
...
}
StampedLock的写锁和悲观读与ReadWriteLock的读写锁功能类似,但乐观读并不是一种加锁操作,允许某一线程在写操作的时候,进行乐观读。
乐观读其实与数据库的乐观锁有异曲同工之妙。
数据库乐观锁,通过版本号version来判断数据是否已更新
SELECT id, ..., version from product_order where id = 777;
//假设此时version为9,
update product_order set version = 10, ... where id = 777 and version = 9
乐观读的编程范式
当乐观读失败时,直接升级为读锁,保证数据访问成功
public class Point {
private int x;
private int y;
private StampedLock lock = new StampedLock();
double distanceFromOrigin() {
long stamp = lock.tryOptimisticRead();
int curX = x;
int curY = y;
if (!lock.validate(stamped)) {
stamp = lock.readLock();
try {
curX = x;
curY = y;
} finally {
lock.unlockRead(stamp);
}
}
return Math.sqrt(curX*curX + curY*curY);
}
}
总结
- StampedLock 支持 可中断的悲观读readLockInterruptibly()和写锁writeLockInterruptibly()
- StampedLock 不支持条件变量
- StampedLock 支持锁升级tryConvertToWriteLock()和降级tryConvertToReadLock()