本文概览:介绍了await执行过程 和 signal执行过程。

1 引入

以wait/notify之于synchronized的作用(synchronized只是保证多个线程互斥的访问这个实例对象,但是如果需要自定义这些线程顺序,那么此时引入了wait/notify) 来理解condition之于AQS同步器作用:实现控制线程占用同步器AQS的顺序。

2 ConditionObject的数据成员

定义了一个condition队列

Snip20180509_74

3 ConditionObject的接口

condition接口如下:

3.1 await

1、awati作用

(1)释放当前线程的同步器,把线程节点加入到条件队列中进行阻塞;

(2)触发release操作,AQS 同步队列中Head节点执行acquire操作。

2、执行流程

3.2  awaitUninterruptibly()

就是线程是中断的状态,也可以继续执行。查看awaitUniterruptible()代码比await()代码少了如下逻辑:

3.3 single

single把条件队列中firstWaiter节点转移到AQS同步队列中,触发await阻塞的线程,从lockSupport.park的位置开始执行acquire。

  • singel操作通过transferForSignal函数来处理firstWaiter节点
  • transferForSignal的作用就是:将条件对列的节点(每一次都是取FiristWaiter节点),放置到同步器的FIFO对列中。

1、transferForSignal的代码如下

问题1 为什么要执行 LockSupport.unpark(node.thread)?

为了执行从await操作如下位置开始执行

60871547

3.4 await(long time, TimeUnit unit)

1、作用

等待某个时间,超过这个时间,线程结点自动进入到同步器的FIFO对列,不再需要等待singal来执行条件对列节点放入到同步器的FIFO对列中。

2、实现

通过LockSupport.parkNanos(this, nanosTimeout);这方法来实现等待时间。如果超过时间阈值,执行transferAfterCancelledWait函数来讲此线程节点加入到同步器的FIFO对列中,不再需要等待singal操作。

3、其他类似的Condition接口

3.4  signalAll()

single就是将条件对列的firstWaiter节点放入到同步器的FIFO对列中。

singleAll就是将条件对列所有线程节点都放置到FIFO对列中。

4 相关问题

4.1 解析Condition的await/single和同步器AQS的acquire/release

1、await实现功能总结

第一步: 当前线程放弃同步器

第二步 :通过LockSupport#park阻塞线程;将线程节点放置到条件队列中。

第三步 :并通过fullRelease来触发同步队列中Head节点。

2、acquire

执行acquire分两种情况:

(1)情况1 可以获取同步器,此时直接运行线程

(2)情况2 没有获取同步器,需要阻塞线程

   通过LockSupport#park阻塞线程;将线程节点放置到同步器的FIFO队列中。

3、signal()功能:

就是将条件队列的线程节点放置到同步器的FIFO对列中。执行LockSupport.unpark操作触发await阻塞的操作。

4、release()功能

对于FIFO对列上的节点线程,最终需要执行realse,通过unpark来运行这个节点的线程

4.2 对于wait线程,下次通过notify通知时,如何保证从wait位置执行程序?

通过LockSupport.park和LockSupport.unpark。

1、执行await操作

执行LockSupport.park方法,然后将线程节点加入条件对列

2、执行single操作

将条件对列的firstWaiter节点转移到同步器的FIFO队列。将来通过Lock.unlock()方法来执行这个线程的unpark,从而让这个线程继续执行。

4.3 Conditon队列和AQS中的FIFO对列比较

1. 两个队列的区别

condition对列为单向对列

AbstractQueueSynchronizer的FIFO对列是双向对列

2 一个node节点是否可以即在Condition对列,又在AbstractQueueSynchronizer对列中

可以。可以参考代码来判断这个条件对列的节点是否在同步对列:

(1)什么时候放将条件对列中节点放到同步对列

在执行await操作,调用checkInterruptWhileWaiting函数。在checkInterruptWhileWaiting函数中将条件对列的节点放置到同步对列,如下代码

(2)什么时候将条件对列中在同步对列的节点删除

在执行addConditionWaiter() 函数时,会执行  unlinkCancelledWaiters();代码如下,清空在条件对列中节点状态不是Node.CONDITION的节点

(全文完)

分类&标签