protectedfinalinttryAcquireShared(int unused) { /* * 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(); //持有写锁的线程可以获取读锁,如果获取锁的线程不是当前线程,则返回-1 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和firstReaderHoldCount firstReader = current; firstReaderHoldCount = 1; } elseif (firstReader == current) { //如果当前线程是首次获取读锁的线程 firstReaderHoldCount++; } else { //更新HoldCounter HoldCounterrh= cachedHoldCounter; if (rh == null || rh.tid != getThreadId(current)) cachedHoldCounter = rh = readHolds.get(); elseif (rh.count == 0) readHolds.set(rh); rh.count++; } return1; } return fullTryAcquireShared(current); }
privatevoiddoReleaseShared() { /* * Ensure that a release propagates, even if there are other * in-progress acquires/releases. This proceeds in the usual * way of trying to unparkSuccessor of head if it needs * signal. But if it does not, status is set to PROPAGATE to * ensure that upon release, propagation continues. * Additionally, we must loop in case a new node is added * while we are doing this. Also, unlike other uses of * unparkSuccessor, we need to know if CAS to reset status * fails, if so rechecking. */ for (;;) { Nodeh= head; if (h != null && h != tail) { intws= h.waitStatus; if (ws == Node.SIGNAL) { if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases unparkSuccessor(h); } elseif (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } if (h == head) // loop if head changed break; } }