/** Returns the number of shared holds represented in count */ staticintsharedCount(int c) { return c >>> SHARED_SHIFT; } /** Returns the number of exclusive holds represented in count */ staticintexclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
protectedfinalbooleantryReleaseShared(int unused) { Threadcurrent= Thread.currentThread(); if (firstReader == current) { // assert firstReaderHoldCount > 0; if (firstReaderHoldCount == 1) firstReader = null; else firstReaderHoldCount--; } else { HoldCounterrh= cachedHoldCounter; if (rh == null || rh.tid != getThreadId(current)) rh = readHolds.get(); intcount= rh.count; if (count <= 1) { readHolds.remove(); if (count <= 0) throw unmatchedUnlockException(); } --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; } }
锁降级
锁降级是指把持住(当前拥有的)写锁,再获取到读锁,随后释放(先前拥有的)写锁的过程
先释放写锁再获取读锁这种分段的不能称为锁降级
主要是为了保证数据的可见性,如果当前线程不获取读锁而直接释放写锁,假设此刻另一个线程(T)获取了写锁并修改了数据,那么当前线程是无法感知线程 T 的数据更新。如果当前线程获取读锁,即遵循锁降级的步骤,则线程T将会被阻塞,知道当前线程使用数据并释放读锁之后,线程T才能获取写锁进行数据更新。
voidprocessCachedData() { rwl.readLock().lock(); if (!cacheValid) { // 必须先释放读锁 rwl.readLock().unlock(); // 锁降级从写锁获取到时开始 rwl.writeLock().lock(); try { // Recheck state because another thread might have // acquired write lock and changed state before we did. if (!cacheValid) { data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.readLock().lock(); } finally { rwl.writeLock().unlock(); // Unlock write, still hold read } }