先来看一下这个Condition的使用场景,在LinkedBlockingQueue(链表的阻塞队列)类中包含如下的定义,通过使用lock.newCondition()方法,可以获得一个Condition对象,说明Condition与ReentrantLock有着重要的关联关系。

Condition对象创建

通常它们的使用方式是如下这样,注意线程1的condition.await()和线程2的condition.signal()方法,后面重点讲解这两个方法。

例子

Condition类是AQS(AbstractQueuedSynchronizer,抽象的队列同步器)的内部类,我们重点来看下这个线程1的condition.await()方法,对里面的几个重要方法进行重点的说明。

await()方法

Node node = addConditionWaiter();//将当前线程包装成Node,然后放入条件等待队列中,注意这个队列和//外面的ReentrantLock的同步等待队列是两个不同的队列,在唤醒时(也就是调用condition.signal()),会把//这个线程先从条件等待队列中移除,然后转移到ReentrantLock的同步等待队列里面去,然后在同步等待队列//中获取锁以后,才能真正的被执行int savedState = fullyRelease(node);//在将当前线程放入到条件等待队列中以后,这个方法会把当前线程//所持有的锁释放掉,这个时候ReentrantLock同步等待队列中的某一个线程会获得锁,然后被激活int interruptMode = 0;while (!isOnSyncQueue(node)) {//判断当前线程如果不存在于ReentrantLock同步队列中,则将当前线程//中断挂起,如果这个线程存在于ReentrantLock同步队列中,那么它已经被中断挂起,则不需要再次中断挂起  LockSupport.park(this);

总结来说就是,将当前线程封装成Node,然后加入到条件等待队列中,释放线程持有的锁,然后将此线程中断挂起。

接下来我们重点来看下线程2的condition.signal()方法,对里面的几个重要方法进行重点的说明。

signal()方法

if (!isHeldExclusively())//判断此线程是不是ReentrantLock锁的独占线程,如果不是则抛出异常,换言之//只有是ReentrantLock锁的独占线程,才能进行唤醒操作,也就是说在执行condition.await()//和condition.signal()方法时,线程必须拿到ReentrantLock锁才可以进行,这也就是Condition //与ReentrantLock有着必要的关联关系    throw new IllegalMonitorStateException();  Node first = firstWaiter;//拿到条件等待线程的第一个Node  if (first != null)    doSignal(first);//第一个Node不为null时,进行唤醒操作

下面来看下doSignal(first)方法的执行逻辑,重点看下其中的transferForSignal(first)方法。

doSignal()方法

transferForSignal()方法

if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))//将Node的节点更新为0,如果更新失败,  //则代表此节点已经被取消了,直接返回失败,遍历下一个条件等待队列的节点。    return false;Node p = enq(node);//重点方法,将当前节点由条件等待队列转移到ReentrantLock的同步等待队列的队尾中去        int ws = p.waitStatus;//此时被转移到同步等待队列的Node的waitStatus应该是0,        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))//将此Node节点的waitStatus更新为-1            LockSupport.unpark(node.thread);//此逻辑不会执行,因为线程从条件等待队列只是被转移到了同步 //等待队列,而且是队尾的位置,如果同步等待队列前面有有其他线程,则会优先于它被唤醒。        return true;

在执行了condition.signal()方法后,会将条件等待队列中的线程移除,然后转移到ReentrantLock的同步等待队列中,后面的逻辑就和ReentrantLock(可重入锁)执行同步等待队列中的线程一样了(这个逻辑不清楚可以查看我的此篇文章(原创)Java的ReentrantLock(可重入锁)详解上篇)。

简单总结下,Condition依赖于ReentrantLock,必须拿到ReentrantLock锁以后,才可以进行await()和single()方法,在执行了await()时,会释放持有的ReentrantLock锁,并把自己加入到条件等待队列中去,在执行了single()时,会把线程从条件等待队列转移到ReentrantLock的同步等待队列中去,然后等待被真正的执行。

java condition_(原创)Java的ReentrantLock(可重入锁)下的Condition相关推荐

  1. 聊聊高并发(二十七)解析java.util.concurrent各个组件(九) 理解ReentrantLock可重入锁

    这篇讲讲ReentrantLock可重入锁,JUC里提供的可重入锁是基于AQS实现的阻塞式可重入锁.这篇 聊聊高并发(十六)实现一个简单的可重入锁 模拟了可重入锁的实现.可重入锁的特点是: 1. 是互 ...

  2. Java并发编程-ReentrantLock可重入锁

    目录 1.ReentrantLock可重入锁概述 2.可重入 3.可打断 4.锁超时 5.公平锁 6.条件变量 Condition 1.ReentrantLock可重入锁概述 相对于 synchron ...

  3. java中多线程reentlock_Java多线程系列——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为"独占锁". ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychr ...

  4. 6※、线程同步、同步锁、同步代码块的使用、同步锁释放的时机、ReentrantLock可重入锁、公平锁与非公平锁的区别、什么是死锁、线程间的通信(生产者和消费者模式)

    线程锁 1.※线程的同步:(要确保对象锁是一致的) 1.未使用同步锁的抢票 2.使用了同步锁的抢票 3.线程-同步代码块的使用 4.同步方法和代码块的区别 5.同步锁释放的时机 练习:多线程生产手机 ...

  5. 1、Lock接口以及ReentrantLock可重入锁

    1.序 文章目录 1.序 2.Lock 接口 3.AbstractQueuedSynchronizer 3.1 双端队列 3.2 state变量 4.ReentrantLock简介以及其非公平锁模式 ...

  6. ReenTrantLock可重入锁(和synchronized的区别)总结

    ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...

  7. 深入剖析基于并发AQS的(独占锁)重入锁(ReetrantLock)及其Condition实现原理

    [版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/75043422 出自[zejian ...

  8. 死磕Java并发:J.U.C之重入锁:ReentrantLock

    ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机制,可以减 ...

  9. Java ReentrantLock可重入锁的源码深度解析

    Java的ReentrantLock的源码实现,包括加锁.解锁的源码,以及公平性.重入性的实现! 文章目录 1 ReentrantLock的概述 1.1 ReentrantLock的API方法 1.2 ...

最新文章

  1. mysql 几十连接_MySQL挑战:10万连接数
  2. 冒泡排序的PHP实现 Bubble Sort
  3. 静态库和共享库之间的区别?
  4. 在PAT上提交Java代码
  5. 聊起 BigTable,让你不再胆怯
  6. spring mvc学习(24):配置maven环境和创建maven项目(建议收藏,超全超详细)
  7. matlab怎么求hadamard,hadamard matlab
  8. 解决applet覆盖遮罩层div的问题
  9. 远哥跟你说 Spring的 classpath 通配符加载配置文件
  10. deepin/ubantu下 mysql 1698错误解决
  11. P1359 租用游艇 洛谷
  12. Nginx负载均衡状态值max_fails和fail_timeout
  13. log4j2 日期换天后,今天的日志打印到了昨天的日志文件里面,rollover混乱
  14. 16岁女孩攻陷著名安全企业HBGary
  15. 第二章:互联网灵魂之TCP/IP(二)
  16. 直播预告|【芯咖秀▪第六期】MCU热的前因后果以及未来到底如何发展!
  17. mysql求及格百分率_关于mysql进行名次的排名和计算及格率的分享
  18. 竞拍系统c语言,asp宝贝儿网络拍卖商城购物系统 v11.0 GBK
  19. TypeScript保存代码时自动编译并运行
  20. 记录Android开发中的问题及解决方法

热门文章

  1. “不一样”的真实渗透测试案例分析
  2. 渗透新手福利---xss到获取cookie入门级
  3. 013 Android锁机病毒分析
  4. CVE-2017-11882漏洞分析
  5. 3.1.4 内存的连续分配管理方式
  6. 对象属性操作函数:hasattr(),getattr(),setattr()
  7. Tomcat在自定义xml文件中配置虚拟目录
  8. Java 中这些常用关键字,总有那么些被你遗忘的
  9. Java提升篇:理解String 及 String.intern() 在实际中的应用
  10. Java集合中HashSet的实现原理