看完ReentrantLock后再来看看ReentrantReadWriteLock读写锁:
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
线程1 readWriteLock.writeLock().lock();
线程1来获取写锁
protected final boolean tryAcquire(int acquires) {
//当前线程1
Thread current = Thread.currentThread();
//state=0,c=0
int c = getState();
//c=0,w=0 int state是32位的二进制
//读写锁把state的低16位作为写锁标志,高16位作为读锁标志
//c=0,它的低16位也是0
int w = exclusiveCount(c);
if (c != 0) {
if (w == 0 || current != getExclusiveOwnerThread())
return false;
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
setState(c + acquires);
return true;
}
//然后走到这,writerShouldBlock()=false,CAS将state=1,并将占有锁线程设为线程1
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
这样线程1成功获取来读锁
线程2 readWriteLock.writeLock().lock();
此时线程2来获取写锁了,c=1,w!=0,但是current != getExclusiveOwnerThread(),返回false加锁失败,然后就加入到队列阻塞等待了,与之前ReentrantLock类似
if (w == 0 || current != getExclusiveOwnerThread())这个说明加了读锁,加了写锁就不能加读锁了
线程3 readWriteLock.readLock().lock(); 此时线程3来获取读锁了
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
int r = sharedCount(c);
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}
return 1;
}
return fullTryAcquireShared(current);
}
此时c=state=1,
exclusiveCount(c) != 0 &&getExclusiveOwnerThread() != current 为true,返回-1 ,可以看出加了写锁,就不能加读锁了 ,读锁与写锁互斥
然后就加入到队列,阻塞等待了,waitStatus=SHARED 表示读锁
假设现在线程1,释放了写锁,然后唤醒了线程2,线程2获取到了读锁
此时 线程3 readWriteLock.writeLock().lock(); 来获取读锁了
r = sharedCount(c); 是state的高16位,线程2已经获取了读锁,所以r!=0,
下面这段代码就是指获取读锁成功后,做的一些记录。像线程2就是firstReader
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}