// 读锁
private final ReentrantReadWriteLock.ReadLock readerLock;// 写锁
private final ReentrantReadWriteLock.WriteLock writerLock;// 同步器
final Sync sync;
1.
2.
3.
4.
5.
6.
ReentrantReadWriteLock构造方法
//默认是非公平锁,可以指定参数创建公平锁
public ReentrantReadWriteLock(boolean fair){//true 为公平锁
sync = fair ? new FairSync(): new NonfairSync();// 这两个 lock 共享同一个 sync 实例,都是由 ReentrantReadWriteLock 的 sync 提供同步实现
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);}
1.
2.
3.
4.
5.
6.
7.
8.
Sync类重要成员变量
// 用来移位
static final int SHARED_SHIFT =16;// 高16位的1
static final int SHARED_UNIT =(1<< SHARED_SHIFT);//65535,16个1,代表写锁的最大重入次数
static final int MAX_COUNT =(1<< SHARED_SHIFT)-1;// 低16位掩码:0b 1111111111111111,用来获取写锁重入的次数
static final int EXCLUSIVE_MASK =(1<< SHARED_SHIFT)-1;// 获取读写锁的读锁分配的总次数
static int sharedCount(int c){ return c >>> SHARED_SHIFT;}// 写锁(独占)锁的重入次数
static int exclusiveCount(int c){ return c & EXCLUSIVE_MASK;}
// 加读锁的方法入口
public void lock(){
sync.acquireShared(1);}
public final void acquireShared(int arg){// tryAcquireShared 返回负数, 表示获取读锁失败,加入到队列中
if (tryAcquireShared(arg)<0)
doAcquireShared(arg);}
final int fullTryAcquireShared(Thread current){// 当前读锁线程持有的读锁次数对象
HoldCounter rh =null;
for (;;){int c = getState();// 说明有线程持有写锁
if (exclusiveCount(c)!=0){// 写锁不是自己则获取锁失败
if (getExclusiveOwnerThread()!= current)
return -1;} else if (readerShouldBlock()){// 条件成立说明当前线程是 firstReader,当前锁是读忙碌状态,而且当前线程也是读锁重入
if (firstReader == current){// assert firstReaderHoldCount >0;} else {
if (rh ==null){// 最后一个读锁的 HoldCounter
rh = cachedHoldCounter;// 说明当前线程也不是最后一个读锁
if (rh ==null|| rh.tid!= getThreadId(current)){// 获取当前线程的 HoldCounter
rh = readHolds.get();// 条件成立说明 HoldCounter 对象是上一步代码新建的
// 当前线程不是锁重入,在 readerShouldBlock() 返回 true 时需要去排队
if (rh.count==0)// 防止内存泄漏
readHolds.remove();}}
if (rh.count==0)
return -1;}}// 越界判断
if (sharedCount(c)== MAX_COUNT)
throw new Error("Maximum lock count exceeded");// 读锁加锁,条件内的逻辑与 tryAcquireShared 相同
if (compareAndSetState(c, c + SHARED_UNIT)){
if (sharedCount(c)==0){
firstReader = current;
firstReaderHoldCount =1;} else if (firstReader == current){
firstReaderHoldCount++;} else {
if (rh ==null)
rh = cachedHoldCounter;
if (rh ==null|| rh.tid!= getThreadId(current))
rh = readHolds.get();
else if (rh.count==0)
readHolds.set(rh);
rh.count++;
cachedHoldCounter = rh;// cache for release
}
return 1;}}}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
doAcquireShared()是在获取读锁失败的时候加入AQS队列的逻辑。
private void doAcquireShared(int arg){// 将当前线程关联到一个 Node 对象上, 模式为共享模式
final Node node = addWaiter(Node.SHARED);boolean failed =true;
try {boolean interrupted =false;
for (;;){// 获取前驱节点
final Node p = node.predecessor();// 如果前驱节点就头节点就去尝试获取锁
if (p == head){// 再一次尝试获取读锁
int r = tryAcquireShared(arg);// r >=0 表示获取成功
if (r >=0){//【这里会设置自己为头节点,唤醒相连的后序的共享节点】
setHeadAndPropagate(node, r);
p.next=null;// help GC
if (interrupted)
selfInterrupt();
failed =false;
return;}}// 是否在获取读锁失败时阻塞 park 当前线程
if (shouldParkAfterFailedAcquire(p, node)&& parkAndCheckInterrupt())
interrupted =true;}} finally {
if (failed)
cancelAcquire(node);}}
public void unlock(){// 释放锁
sync.release(1);}
public final boolean release(int arg){// 尝试释放锁
if (tryRelease(arg)){
Node h = head;// 头节点不为空并且不是等待状态不是 0,唤醒后继的非取消节点
if (h !=null&& h.waitStatus!=0)
unparkSuccessor(h);
return true;}
return false;}
protected final boolean tryRelease(int releases){
if (!isHeldExclusively())
throw new IllegalMonitorStateException();int nextc = getState()- releases;// 因为可重入的原因, 写锁计数为 0, 才算释放成功
boolean free = exclusiveCount(nextc)==0;
if (free)// 设置占用线程为null
setExclusiveOwnerThread(null);
setState(nextc);
return free;}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
2.读锁释放流程
ReadLock类的unlock()方法是释放共享锁的入口方法。
public void unlock(){
sync.releaseShared(1);}
public final boolean releaseShared(int arg){
if (tryReleaseShared(arg)){
doReleaseShared();
return true;}
return false;}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
tryReleaseShared()方法是由AQS提供的模板方法,由自定义同步器实现。
protected final boolean tryReleaseShared(int unused){//自选
for (;;){int c = getState();int nextc = c - SHARED_UNIT;// 读锁的计数不会影响其它获取读锁线程, 但会影响其它获取写锁线程,计数为 0 才是真正释放
if (compareAndSetState(c, nextc))// 返回是否已经完全释放了
return nextc ==0;}}