protectedfinalinttryAcquireShared(intunused){/* * Walkthrough: * 1. If write lock held by another thread, fail. * 2. Otherwise, this thread is eligible for * lock wrt state, so ask if it should block * because of queue policy. If not, try * to grant by CASing state and updating count. * Note that step does not check for reentrant * acquires, which is postponed to full version * to avoid having to check hold count in * the more typical non-reentrant case. * 3. If step 2 fails either because thread * apparently not eligible or CAS fails or count * saturated, chain to version with full retry loop. */Threadcurrent=Thread.currentThread();intc=getState();if(exclusiveCount(c)!=0&&getExclusiveOwnerThread()!=current)return-1;intr=sharedCount(c);if(!readerShouldBlock()&&r<MAX_COUNT&&compareAndSetState(c,c+SHARED_UNIT)){if(r==0){firstReader=current;firstReaderHoldCount=1;}elseif(firstReader==current){firstReaderHoldCount++;}else{HoldCounterrh=cachedHoldCounter;if(rh==null||rh.tid!=current.getId())cachedHoldCounter=rh=readHolds.get();elseif(rh.count==0)readHolds.set(rh);rh.count++;}return1;}returnfullTryAcquireShared(current);}
finalintfullTryAcquireShared(Threadcurrent){/* * This code is in part redundant with that in * tryAcquireShared but is simpler overall by not * complicating tryAcquireShared with interactions between * retries and lazily reading hold counts. */HoldCounterrh=null;for(;;){intc=getState();if(exclusiveCount(c)!=0){if(getExclusiveOwnerThread()!=current)return-1;// else we hold the exclusive lock; blocking here// would cause deadlock.}elseif(readerShouldBlock()){// Make sure we're not acquiring read lock reentrantlyif(firstReader==current){// assert firstReaderHoldCount > 0;}else{if(rh==null){rh=cachedHoldCounter;if(rh==null||rh.tid!=current.getId()){rh=readHolds.get();if(rh.count==0)readHolds.remove();}}if(rh.count==0)return-1;}}if(sharedCount(c)==MAX_COUNT)thrownewError("Maximum lock count exceeded");if(compareAndSetState(c,c+SHARED_UNIT)){if(sharedCount(c)==0){firstReader=current;firstReaderHoldCount=1;}elseif(firstReader==current){firstReaderHoldCount++;}else{if(rh==null)rh=cachedHoldCounter;if(rh==null||rh.tid!=current.getId())rh=readHolds.get();elseif(rh.count==0)readHolds.set(rh);rh.count++;cachedHoldCounter=rh;// cache for release}return1;}}}
fullTryAcquireShared首先会判断若其他线程持有写锁,则会阻塞。若readerShouldBlock返回true,则进入if分支,如果当前线程不是第一个读线程,同时当前线程是之前没有持有读锁,则会从ThreadLocal中移除HoldCounter,最后如果count仍是-1,则直接返回-1,阻塞当前线程。接着下来的代码就是对tryAcquireShared CAS state失败的处理,逻辑类似。
protectedfinalbooleantryReleaseShared(intunused){Threadcurrent=Thread.currentThread();if(firstReader==current){// assert firstReaderHoldCount > 0;if(firstReaderHoldCount==1)firstReader=null;elsefirstReaderHoldCount--;}else{HoldCounterrh=cachedHoldCounter;if(rh==null||rh.tid!=current.getId())rh=readHolds.get();intcount=rh.count;if(count<=1){readHolds.remove();if(count<=0)throwunmatchedUnlockException();}--rh.count;}for(;;){intc=getState();intnextc=c-SHARED_UNIT;if(compareAndSetState(c,nextc))// Releasing the read lock has no effect on readers,// but it may allow waiting writers to proceed if// both read and write locks are now free.returnnextc==0;}}
protectedfinalbooleantryAcquire(intacquires){/* * Walkthrough: * 1. If read count nonzero or write count nonzero * and owner is a different thread, fail. * 2. If count would saturate, fail. (This can only * happen if count is already nonzero.) * 3. Otherwise, this thread is eligible for lock if * it is either a reentrant acquire or * queue policy allows it. If so, update state * and set owner. */Threadcurrent=Thread.currentThread();intc=getState();intw=exclusiveCount(c);if(c!=0){// (Note: if c != 0 and w == 0 then shared count != 0)if(w==0||current!=getExclusiveOwnerThread())returnfalse;if(w+exclusiveCount(acquires)>MAX_COUNT)thrownewError("Maximum lock count exceeded");// Reentrant acquiresetState(c+acquires);returntrue;}if(writerShouldBlock()||!compareAndSetState(c,c+acquires))returnfalse;setExclusiveOwnerThread(current);returntrue;}