Condition源码
2021-08-18 10:02:24 3 举报
Condition源码
作者其他创作
大纲/内容
true自旋进入阻塞队列的队尾并返回node在阻塞队列的前驱节点因为唤醒依靠前驱节点操作
从条件队列队头往后遍历找出第一个需要转移的 node因为有些线程会取消排队,但是可能还在队列中
Thread.interrupted()
condition.await()
检查条件队列的最后一个节点是否取消等待waitStatus不等于-2时表示已取消
do ...while循环遍历条件队列
如果一个线程在不持有 lock 的基础上进入条件队列,释放锁时就会进入异常分支,这个已经入队的节点之后会被后继的节点”请出去“
获取锁才能调用await
node = addConditionWaiter()
释放锁 并反返回之前state值因为await之前必线程先要拿到锁此时线程已经进入队列需要释放锁给其它线程
将当前线程初始为NodewaitStatus=-2插入队列尾部返回node
添加到 condition 的条件队列中
LockSupport.unpark(node.thread)
new Node()
transferForSignal(Node node)
release(savedState)
判断线程中断状态true则抛出中断异常
T2线程
return false
让当前线程进入等待可被中断
LockSupport.park(this)
while (!isOnSyncQueue(node))
int ws = p.waitStatus
unlinkCancelledWaiters()
p = enq(node)
false线程挂起
Condition condition = lock.newCondition()经常可以用在生产者-消费者的场景依靠ReentrantLock,必须获取到锁才能进行操作
(!isHeldExclusively())
获取条件队列队头节点
完全释放独占锁,如果有重入锁次数state也置为0
CAS更新waitStatus=-2更新w为0
t != null && t.waitStatus != Node.CONDITION
condition.signal()
true遍历条件队列清楚所有已取消的节点
唤醒的线程必须持有当前的独占锁判断当前线程是否是持有锁的线程
将 firstWaiter 指向 first 节点后面的第一个,如果将 first 移除后,后面没有节点在等待了,那么需要将 lastWaiter 置为 null如果 first 转移不成功,那么选择 first 后面的第一个节点进行转移
Node first = firstWaiter
ture说明当前线程已被唤醒了将进入阻塞队列,参与竞争取锁
获取锁
return true
唤醒等待了最久的线程
判断节点是否已经转移到阻塞队列signal 的时候需要将节点从移到阻塞队列这样次才能等待获取锁
savedState = fullyRelease(node)
false
获取队尾节点
Condition 的实现类 AbstractQueuedSynchronizer 类中的 ConditionObject1.条件队列的第一个节点 Node firstWaiter2.条件队列的最后一个节点Node lastWaiter3.每个 condition 有一个关联的条件队列4.await方法将当前线程放入条件队列然后阻塞5.signal触发一次唤醒,唤醒的是队头,然后移到阻塞队列的队尾,等待获取锁,获取锁后 await 方法才能返回,继续往下执行
doSignal(first)
T1线程
Node t = lastWaiter
0 条评论
回复 删除
下一页