StampedLock有三种模式,读写 可以 相互转换:
获得独占写锁:
long writeLock()
:阻塞式获取锁
long tryWriteLock()
:尝试获取锁,如返回0表示没有获得锁
long tryWriteLock(long time, TimeUnit unit)
:尝试获取锁,如返回0表示没有获得锁
long writeLockInterruptibly()
:可中断式获取读锁
释放写锁:
void unlockWrite(long stamp)
boolean tryUnlockWrite
:尝试释放写锁,如果线程持有写锁,释放,返回true,否则返回false
获取读锁:
long readLock()
:阻塞式非独占获取锁 。
long tryReadLock()
:尝试获得写锁,如返回0表示没有获得锁
long tryReadLock(long time , TimeUnit unit)
:尝试获得写锁,如返回0表示没有获得锁
long readLockInterruptibly()
:可中断式获取读锁
释放读锁:
void unlockRead (long stamp)
boolean tryUnlockRead()
:尝试释放对读锁的一个持有;如果持有,则释放,返回true,否则返回false
获取乐观读锁
long tryOptimisticRead()
:当被其它线程占用时,将返回0。
转换模式:
long tryConvertToOptimisticRead(long stamp)
long tryConvertToReadLock(long stamp)
long tryConvertToWriteLock(long stamp)
判断锁的当前状态(模式)
boolean isWriteLocked()
boolean isReadLocked()
为了优化老代码中的读写锁,StampedLock提供了三个方法将自身转为读写锁:
Lock asReadLock()
Lock asWriteLock()
ReadWriteLock asReadWriteLock()
其它API
boolean validate(long stamp)
:参数为乐观锁票据
void unlock(long stamp)
:释放锁,如果锁的状态匹配给入的stamp,释放锁的对应模式
例子:使用StampedLock 来做缓存的并发控制,有缓存put和get方法:
import org.springframework.util.StringUtils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.StampedLock;
public class StampedLockCache {
private final Map<Integer , String> cache = new ConcurrentHashMap<>();
private final StampedLock stampedLock = new StampedLock();
public void put(Integer key , String value) {
// 上写锁
long stamp = stampedLock.writeLock();
try {
cache.put(key , value);
} finally {
// 释放写锁
stampedLock.unlockWrite(stamp);
}
}
public String get(Integer key) {
// 先获取乐观锁
long stamp = stampedLock.tryOptimisticRead();
// 先尝试通过乐观锁方式读取数据
String value = cache.get(key);
// 校验是否被其它线程修改过,true:表示未修改 false:修改过,表示需要加悲观锁
if (!stampedLock.validate(stamp)) {
// 上悲观锁
stamp = stampedLock.readLock();
try {
value = cache.get(key);
} finally {
stampedLock.unlock(stamp);
}
}
return value;
}
public String putIfNotExist(Integer key , String value) {
long stamp = stampedLock.readLock();
String currentValue = cache.get(key);
try {
while (StringUtils.isEmpty(currentValue)) {
// 尝试锁升级,读锁升级为写锁
long wstamp = stampedLock.tryConvertToWriteLock(stamp);
if (wstamp != 0L) { // 不为0表示锁升级成功
stamp = wstamp;
currentValue = value;
// 数据写到缓存里
cache.put(key , value);
break;
}
else { // 锁升级失败
// 释放读锁
stampedLock.unlockRead(stamp);
stamp = stampedLock.writeLock();
}
}
}finally {
// 释放所有的锁
stampedLock.unlock(stamp);
}
return currentValue;
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://smilenicky.blog.csdn.net/article/details/121694186
内容来源于网络,如有侵权,请联系作者删除!