ReentrantReadWriteLock 读写锁
2021-12-09 15:55:49 11 举报
ReentrantReadWriteLock 读写锁
作者其他创作
大纲/内容
尝试失败
readHolds获取当前线程读锁的次数并加一
获取成功
head
write
read
。。。
releaseShared
doReleaseShared
如果有共享锁或持有独占锁的线程不是当前线程,则尝试失败否则修改 state
readerShouldBlock判断是否需要阻塞
当前共享线程是否为 0
通过readHolds对每个线程自己的计数器进行--
为 0
parkAndCheckInterrupt阻塞线程,等待唤醒
firstReader是否为当前线程
是
如果有中断则返回 true
tryReleaseShared
writerShouldBlock
失败
acquireShared
addWaiter添加独占锁到队列尾部
parkAndCheckInterrupt
公平
前置节点是否为头节点
否
setHeadAndPropagate把当前节点设置为头结点,并传播
可以防止这种
这种情况防不住
就是读锁计数减-
公平锁判断阻塞队列是否有有效节点非公平锁直接返回 false
tryAcquire
获取共享锁成功
cas 尝试修改 state
exclusiveCount如果有写锁并且不是当前线程则获取失败
简单说就是把前置节点waitStatus设置为SIGNAL(-1)
是否为公平锁
tryAcquireShared尝试获取共享锁
cas 修改 state获取共享锁
tryAcquire尝试获取锁成功后设置头结点
如果共享锁的数量等于 0
ReadLock.lock
前置节点是否为头结点
不为 0
doReleaseShared如果还有剩余的可申请资源,且后续节点为共享节点,则继续唤醒下一个
ReadLock.unlock
firstReaderHoldCount++;
addWaiter添加一个共享节点到队尾
for (;;)
LockSupport#park阻塞,等待 unpark
acquire
firstReaderHoldCount--
doAcquireShared获取共享锁
false
apparentlyFirstQueuedIsExclusive简单来说就是如果头结点的下一个节点为共享节点就可以不阻塞可能会造成写锁饥饿
hasQueuedPredecessors如果队列中有有效节点,则直接阻塞
shouldParkAfterFailedAcquire
非公平
shouldParkAfterFailedAcquire把前置节点设为SIGNAL(-1)
fullTryAcquireShared完整的获取读锁逻辑基本上与上面类似
state是否为 0
设置成功
WriteLock.lock
设置firstReader为当前线程设置firstReaderHoldCount为 1
0 条评论
下一页