Java并发工具AQS条件队列Condition实现详解

while(某个条件) {

condition1.await();

}

lock1.unlock();

参照await的代码进行分析。首先,await()可以响应线程中断,所以一开始先判断这个时候有没有被中断(即await还没开始任何操作就遇到了中断,也许是不耐烦的用户操作引起的)。然后,把当前线程放入条件队列,释放之前已持有的锁(锁中的状态保存到线程的本地变量)。再然后,不断的查询代表当前线程的结点是否已经在锁队列上,如果不在锁队列上则阻塞。因为,把当前线程结点移到锁队列上的一定是另外一个线程(通过调用signal())。当阻塞唤醒(即从LockSupport.park()放回)之后,且查询到当前线程结点已在锁队列上时,说明此时已有其他线程成功调用了signal()或signalAll(),然后执行争夺锁的操作并把之前的锁状态还原回去,即通过acquireQueued()完成。acquireQueued()只有在成功获得锁以后才会返回,最后检查一下在前面的时间里有没有中断,如果有中断则抛出异常。Javadoc中说中断与方法的成功返回之前,中断必须优先响应,这就是因为前面的中断信息只是被记录了下来,没有及时处理,很可能是在很早之前就收到了,直到最后才有机会处理。所以,中断比上述的阻塞循环结果优先。

public final void await() throws InterruptedException {

if (Thread.interrupted())

throw new InterruptedException();

Node node = addConditionWaiter();

int savedState = fullyRelease(node);

int interruptMode = 0;

while (!isOnSyncQueue(node)) {

LockSupport.park(this);

if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)

break;

}

if (acquireQueued(node, savedState) && interruptMode != THROW_IE)

interruptMode = REINTERRUPT;

if (node.nextWaiter != null) // clean up if cancelled

unlinkCancelledWaiters();

if (interruptMode != 0)

reportInterruptAfterWait(interruptMode);

}

其他的awaitX()系列操作,只是在阻塞循环体中增加了等待时间判断、检查有没有中断以尽早跳出循环的逻辑而已。

在await()进行等待的操作中,第一个操作是把线程放入等待队列,这是addConditionWaiter()完成的。addConditio

  • 27
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值