ReadWriteLock(ReentrantReadWriteLock)
概述
A {@code ReadWriteLock} maintains a pair of associated {@link Lock locks}, one for read-only operations and one for writing.
ReadWriteLock包含一对关联的操作:只读、只写
The {@link #readLock read lock} may be held simultaneously by multiple reader threads, so long as there are no writers.The {@link #writeLock write lock} is exclusive.
读锁可以被多个读线程同时持有,写锁是互斥的;
A read-write lock allows for a greater level of concurrency in accessing shared data than that permitted by a mutual exclusion lock.
ReadWriteLock比互斥锁,有更高的的并发性;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public interface ReadWriteLock { /** * Returns the lock used for reading. * * @return the lock used for reading */ Lock readLock(); /** * Returns the lock used for writing. * * @return the lock used for writing */ Lock writeLock(); } |
ReentrantReadWriteLock
概述
An implementation of {@link ReadWriteLock} supporting similar semantics to {@link ReentrantLock}.
一个ReadWriteLock实现;
This class has the following properties:
链路
ReentrantReadWriteLock.ReadLock
lock()
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | // java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock.lock public void lock() { sync.acquireShared( 1 ); } // java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared public final void acquireShared( int arg) { if (tryAcquireShared(arg) < 0 ) doAcquireShared(arg); } // java.util.concurrent.locks.ReentrantReadWriteLock.Sync.tryAcquireShared protected final int tryAcquireShared( int unused) { /* * Walkthrough: * 1. If write lock held by another thread, fail. 写lock被其他线程持有,获取读lock失败 * 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. */ 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 { ReentrantReadWriteLock.Sync.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); } // java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireShared private void doAcquireShared( int arg) { 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); if (r >= 0 ) { setHeadAndPropagate(node, r); p.next = null ; // help GC if (interrupted) selfInterrupt(); failed = false ; return ; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true ; } } finally { if (failed) cancelAcquire(node); } } |
unlock()
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | // java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock.unlock public void unlock() { sync.releaseShared( 1 ); } // java.util.concurrent.locks.AbstractQueuedSynchronizer.releaseShared /** * Releases in shared mode. Implemented by unblocking one or more * threads if {@link #tryReleaseShared} returns true. */ public final boolean releaseShared( int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true ; } return false ; } // java.util.concurrent.locks.ReentrantReadWriteLock.Sync.tryReleaseShared protected final boolean tryReleaseShared( int unused) { Thread current = Thread.currentThread(); if (firstReader == current) { // assert firstReaderHoldCount > 0; if (firstReaderHoldCount == 1 ) firstReader = null ; else firstReaderHoldCount--; } else { Sync.HoldCounter rh = cachedHoldCounter; if (rh == null || rh.tid != getThreadId(current)) rh = readHolds.get(); int count = rh.count; if (count <= 1 ) { readHolds.remove(); if (count <= 0 ) throw unmatchedUnlockException(); } --rh.count; } for (;;) { int c = getState(); int nextc = 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. return nextc == 0 ; } } // java.util.concurrent.locks.AbstractQueuedSynchronizer.doReleaseShared /** * Release action for shared mode -- signals successor and ensures * propagation. (Note: For exclusive mode, release just amounts * to calling unparkSuccessor of head if it needs signal.) */ private void doReleaseShared() { /* * 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 (;;) { Node h = head; if (h != null && h != tail) { int ws = h.waitStatus; if (ws == Node.SIGNAL) { if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0 )) continue ; // loop to recheck cases unparkSuccessor(h); } else if (ws == 0 && !compareAndSetWaitStatus(h, 0 , Node.PROPAGATE)) continue ; // loop on failed CAS } if (h == head) // loop if head changed break ; } } |
ReentrantReadWriteLock.WriteLock
lock()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?