特点:在读写锁中,读锁是允许多个线程同时访问的,但是在写锁访问的时候其他企图访问读锁和写锁都是被阻塞的。
历史:在jdk5之前,假如有场景:大部分都是读的场景,写的场景很少,但是写之后的数据要对所有的读所见。
java中的读写锁是RenntrantReadWriteLock,它具有如下特点,公平性选择,重入,降级锁,但是没有升级锁。
RenntrantReadWriteLock内部的一些工具方法:
int getReadLockCount():返回当前读锁被获取的次数,总次数和线程数没关系
int getReadHoldCount():返回当前线程获取读锁的次数,
boolean isWriteLockd():判断写锁是否被获取
int getWriteHoldCont():返回当前线程获取写锁的次数
实例:
public class lock {
static Map<String,Object> map = new HashMap<>();
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
//读锁
static Lock r = rwl.readLock();
//写锁
static Lock w = rwl.writeLock();
public static final Object get(String key){
r.lock();
try {
return map.get(key);
}finally {
r.unlock();
}
}
public static final Object put(String key,Object value){
w.lock();
try {
return map.put(key,value);
}finally {
w.unlock();
}
}
public static final void clear(){
w.lock();
try {
map.clear();
}finally {
w.unlock();
}
}
}
写锁是一个重入的过程,再次获得增加写锁的状态。
如果当前线程获取写锁的时候,读锁已经被其他线程获取,则当前线程进入等待状态。
ReentrantReadWriteLock的tryAcquire方法:
protected final boolean tryAcquir(int acquire){
Thread current = Thread.currentThread();
//获取同步状态值 0代表没有被持有
int c = getState();
//获取写状态
int w = exclusiveCount(c);
if(c!=0){
//读锁被占有了,或者持有锁线程不是当前线程
if(w == 0 || current !=getExclusiveOwnerThread()){
return false;
}
//大于最大值
if(w + exclusiveCount(acquires) > MAX_COUNT)
throw ...
//否则增加状态,这里是当前线程重入了
setState(c);
return true;
//
if(writeShouldBolck() || !compareAndSetState(c,c+acquires)){
return false;
}
//当前线程获得锁
setExclusiverOwnerThread(current);
return ture;
}