java并发-AQS.ObjectCondition源码解析

原创 2014年12月29日 15:43:15

1 什么是条件队列

       它使得一组线程能够通过某种方式来等待特定的条件变成真,条件队列的元素是一个个正在等待状态的线程。对象的内置锁(synchronized语义对应的同步机制),关联着一个内置的条件队列。Objectwait/notify/notifyAll等方法构成了内部条件队列的API(即将内部锁与内部条件队列关联的机制)。 内部条件队列是需要内置锁保护的,即:需要调用对象X中的条件队列,必须持有对象X上的锁。这是因为状态处于并发环境下,“等待依赖状态的某个条件”与“维护状态的一致性”是绑定在一起的。

      条件队列提供了一种挂起方式,当某个线程等待的条件非真时,挂起自己并释放锁,一旦等待条件为真,则立即醒来。这也是条件队列提供的主要功能。

2 显式条件队列

      与内置锁对应的是显式锁,显式锁关联的条件队列是显式条件队列。内置锁的局限表现在每个内置锁只能关联一个条件队列,当线程需要等待多个条件时,则需要同时获取多个内置锁。 显式锁可以与多个条件队列关联,Condition是显式锁的条件队列,它是Objectwait/notify/notifyAll等方法的扩展。提供了在一个对象上设置多个等待集合的功能,即一个对象上设置多个等待条件。

     Condition也称为条件队列,与内置锁关联的条件队列类似,它是一种广义的内置条件队列。它提供给线程一种方式使得该线程在调用wait方法后执行挂起操作,直到线程等待的某个条件为真时被唤醒。 条件队列必须跟锁一起使用,因为对共享状态变量的访问发生在多线程环境下,原理与内部条件队列一样。一个Condition的实例必须跟一个Lock绑定。因此, Condition一般作为Lock的内部类现。

       AQS对条件队列的实现类图如下,它维护了一个双向链表表示的队列。

3 条件队列的节点状态

      调用条件队列的等待操作,会设置节点的waitingStatus为Condition,标识当前节点正处于条件队列中。条件队列的节点状态转换图如下:

         Node的各个状态的主要作用:Cancelled主要是解决线程在持有锁时被外部中断的逻辑,AQS的可中断锁获取方法lockInterrutible()是基于该状态实现的。显式锁必须手动释放锁,尤其是有中断的环境中,一个线程被中断可能仍然持有锁,所以必须注意在finally中unlock。Condition则是支持条件队列的等待操作,是Lock与条件队列关联的基础。Signal是阻塞后继线程的标识,一个等待线程只有在其前驱节点的状态是SIGNAL时才会被阻塞,否则一直执行自旋尝试操作,以减少线程调度的开销。

4 等待和唤醒操作

        条件队列上的等待和唤醒操作,本质上是节点在AQS线程等待队列和条件队列之间相互转移的过程,当需要等待某个条件时,线程会将当前节点添加到条件队列中,并释放持有锁;当某个线程执行条件队列的唤醒操作,则会将条件队列的节点转移到AQS等待队列。每个Condition就是一个条件队列,可以通过Lock的newCondition创建多个等待条件。AQS的条件队列,它的等待和唤起操作流程如下:

         结论:显式条件队列弥补了内置条件队列只能关联一个条件的缺陷,同时继承了Lock对象的公平性。在Condition对象中,与Object的wait/notify/notifyAll对应的扩展方法是await/signal/signallAll,同时它也具有Object的这三个方法,所以使用的时候需要注意使用版本的正确。另外,显式锁必须遵从特定的使用规范,先lock,然后再在finally中unlock,以确保锁必然会被正确释放。

        此外,AQS的两个队列都是链表队列,类的方法代码都相当简洁,尤其是节点移除队列操作过程中,都及时释放了所占内存。读源码,可以学习到一种编码的严谨性思想,锻炼自己关注GC的意识。这是我见到过的第三处及时释放GC的的代码了。从最初的ArrayList的元素remove中,然后是HashMap的动态扩容数组转移操作,最近看AQS的元素唤醒和锁释放操作。关注GC的确是最近开始形成的一种编程意识。

版权声明:本文为博主原创文章,未经博主允许不得转载。

jdk1.8 J.U.C并发源码阅读------AQS之conditionObject内部类分析

jdk1.8中java.util.concurrent包中源码阅读笔记。
  • u011470552
  • u011470552
  • 2017年08月02日 10:10
  • 426

Condition的await-signal流程详解

大概的整个过程是: 调用await的线程都会进入一个Condition队列。调用signal的线程每一次都会从firstWaiter开始找出未取消的Condition Node放到rel...
  • luonanqin
  • luonanqin
  • 2014年12月12日 15:53
  • 11160

《Java源码分析》:Condition

《Java源码分析》:Condition如下这篇博文讲解的Condition真心将的好,自己结合了源码也基本上对Condition有了一个大致的了解。写篇博客记录下。参考博客地址如下:http://i...
  • u010412719
  • u010412719
  • 2016年08月01日 22:01
  • 3105

怎么理解ConditionObject,sync.newCondition()

在java.util.concurrent包中,有两个很特殊的工具类,Condition和ReentrantLock,使用过的人都知道,ReentrantLock(重入锁)是jdk的concurren...
  • qq_22929803
  • qq_22929803
  • 2016年08月28日 18:53
  • 848

Java并发编程-Lock和condition的原理及AQS的运用

AQS的全称为(AbstractQueuedSynchronizer),这个类也是在java.util.concurrent.locks下面。这个类似乎很不容易看懂,因为它仅仅是提供了一系列公共的方法...
  • chenchaofuck1
  • chenchaofuck1
  • 2016年08月16日 19:33
  • 2611

聊聊高并发(二十一)解析java.util.concurrent各个组件(三) 深入理解AQS(一)

AQS是AbstractQueuedSynchronizer的缩写,AQS是Java并包里大部分同步器的基础构件,利用AQS可以很方便的创建锁和同步器。它封装了一个状态,提供了一系列的获取和释放操作,...
  • ITer_ZC
  • ITer_ZC
  • 2014年11月06日 14:16
  • 4290

java Condition源码分析

JUC提供了Lock可以方便的进行锁操作,但是有时候我们也需要对线程进行条件性的阻塞和唤醒,这时我们就需要condition条件变量,它就像是在线程上加了多个开关,可以方便的对持有锁的线程进行阻塞和唤...
  • qilixiang012
  • qilixiang012
  • 2015年04月23日 09:21
  • 1670

java并发锁ReentrantLock源码分析二之Condition实现原理

本文深入分析了并发锁ReentrantLock Condtion的实现原理,一个很重要的关键是await先释放锁,然后阻塞,在条件队列中等待被唤醒,每个CondtionObject维护着一个条件队列,...
  • prestigeding
  • prestigeding
  • 2016年11月14日 13:55
  • 2013

java并发-AQS.ObjectCondition源码解析

1 什么是条件队列        它使得一组线程能够通过某种方式来等待特定的条件变成真,条件队列的元素是一个个正在等待状态的线程。对象的内置锁(synchronized语义对应的同步机制),关联着一个...
  • wojiushiwo945you
  • wojiushiwo945you
  • 2014年12月29日 15:43
  • 2900

Object和Condition对应的操作线程方法

wait()、notify()和notifyAll()是 Object类 中的方法 从这三个方法的文字描述可以知道以下几点信息: 1)wait()、notify()和notifyAll...
  • caokun12321
  • caokun12321
  • 2016年08月21日 17:16
  • 299
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java并发-AQS.ObjectCondition源码解析
举报原因:
原因补充:

(最多只允许输入30个字)