之前对AbstractQueuedSynchronizer(AQS)同步队列与Condition等待队列的功能一直不是很清晰,没太清楚地区分开二者的区别和联系,最近研究了一下分享出来。

1.同步队列和等待队列简述

AQS维护的队列是当前等待资源的队列。当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成为一个节点并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态。

每个Condition维护着一个队列,该队列的作用是维护一个等待singal信号的队列。

    //AQS中的Node属性static final class Node {...volatile int waitStatus;//等待状态volatile Node prev;//前驱节点volatile Node next;//后驱节点volatile Thread thread;//获取同步状态的线程,当前执行线程Node nextWaiter;//等待队列中的后继节点...}

从上述Node结构可以看出,其实同步队列和等待队列使用的是同一个Node类型AbstractQueuedSynchronizer.Node。

2.同步队列和等待队列区别与协同机制

从简述中我们可知,同步队列和等待队列的作用是不同的。最重要的区别是:每个线程只能存在于同步队列或等待队列中的一个

下面我们举一个具体的例子来说明同步队列和等待队列之间的区别与协同工作:

  1. 同步队列的初始状态为下图,同步队列中包含线程A(节点A)和线程B(节点B),线程调用reentrantLock.lock()时,线程被加入到AQS同步队列中

  2. 线程A(节点A)调用condition.await()方法时,线程A(节点A)从AQS同步队列中被移除,对应操作是锁的释放; 线程A(节点A)接着被加入到Condition等待队列,因为线程需要singal信号。
  3. 线程B(节点B)由于线程A(节点A)释放锁被唤醒,判断成为同步队列头结点且同步状态为0可以获取锁;线程B(节点B)获取锁。

  4. 线程B(节点B)调用singal()方法,Condition等待队列中有一个节点A,把它取出来加入到AQS同步队列中。这时候线程A(节点A)并没有被唤醒。

  5. 线程B(节点B)singal方法执行完毕,调用reentrantLock.unLock()方法释放锁。线程A(节点A)成为AQS首节点并且同步状态可获取,线程A(节点A)被唤醒,继续执行。
  6. AQS从头到尾顺序唤醒线程,直到等待队列中的线程被执行完毕结束。

只有发送singal信号的线程调用reentrantLock.unLock()后,因为它已经被加入到AQS同步队列并且成为同步队列头结点,所以线程才会被唤醒。

参考:

  • 特别感谢《Java并发编程的艺术》
  • http://ifeve.com/understand-condition/

AbstractQueuedSynchronizer同步队列与Condition等待队列协同机制相关推荐

  1. 一个object上拥有一个同步队列和一个等待队列

    https://zhidao.baidu.com/question/363047394862518892.html

  2. 线程状态切换之等待队列和同步队列

    转自:https://blog.csdn.net/weixin_37695911/article/details/106668435 线程的主要状态及切换: 1.初始-NEW(还未调用start()) ...

  3. 同步器AQS中的同步队列与等待队列

    在单纯地使用锁,比如ReentrantLock的时候,这个锁组件内部有一个继承同步器AQS的类,实现了其抽象方法,加锁.释放锁也只是涉及到AQS中的同步队列而已,那么等待队列又是什么呢? 当使用Con ...

  4. java同步队列_Java 中队列同步器 AQS(AbstractQueuedSynchronizer)实现原理

    前言 在 Java 中通过锁来控制多个线程对共享资源的访问,使用 Java 编程语言开发的朋友都知道,可以通过 synchronized 关键字来实现锁的功能,它可以隐式的获取锁,也就是说我们使用该关 ...

  5. 浅谈AQS(AbstractQueuedSynchronizer,同步队列)

    1.1 同步队列:队列中存放排队等待锁的线程,每个线程放入队列时会被包装为Node类,如下图.  1.2 抢锁:调用lock方法,如果抢锁成功(CAS成功,或者是重入--state计数加1),那么in ...

  6. 并发编程-15并发容器(J.U.C)核心 AbstractQueuedSynchronizer 抽象队列同步器AQS介绍

    文章目录 J.U.C脑图 J.U.C核心AQS简介 AQS底层数据结构 AQS特点 J.U.C脑图 为了体现出AQS和线程池的重要性,上图单独将AQS和线程池拿出来了. J.U.C的构成如下: J.U ...

  7. java8 同步队列_秋招之路8:JAVA锁体系和AQS抽象队列同步器

    整个的体系图 悲观锁,乐观锁 是一个广义概念:体现的是看待线程同步的不同角度. 悲观锁 认为在自己使用数据的时候一定有别的线程来修改数据,在获取数据的时候会先加锁,确保数据不被别的线程修改. 实现:关 ...

  8. 死磕Java并发:J.U.C之AQS:CLH同步队列

    本文转载自公号:Java技术驿站 在上篇文章"死磕Java并发:J.U.C之AQS简介"中提到了AQS内部维护着一个FIFO队列,该队列就是CLH同步队列. CLH同步队列是一个F ...

  9. AQS独占式同步队列入队与出队

    入队 Node AQS同步队列和等待队列共用同一种节点结构Node,与同步队列相关的属性如下. prev 前驱结点 next 后继节点 thread 入队的线程 入队节点的状态 INITIAl 0 初 ...

最新文章

  1. IT团队之非正式沟通
  2. k8s,nginx备份日志脚本
  3. 在建工程的管理是怎样在总帐中实现
  4. sqlserver导出带数据的脚本文件
  5. LVM逻辑卷,RAID磁盘阵列
  6. 方舟手游服务器设置文件翻译,方舟手游咋设置翻译
  7. 图像超分辨率增强ESRGAN运行教程,有数据
  8. lisp画表盘刻度线_Lisp-Stat翻译 —— 第九章 统计绘图窗体
  9. java突击面试章程
  10. [TJOI2019]唱、跳、rap和篮球——NTT+生成函数+容斥
  11. coq 函数式编程--Basics.v
  12. C/C++编程学习 - 第6周 ⑦ 分离整数的各个数位
  13. java控制台输入做界面_Java控制台输入
  14. zk的session
  15. finalcut剪切快捷键_Final Cut Pro X 常用键盘快捷键
  16. python打开各种文件格式_使用python读取数据科学最常用的文件格式(转)
  17. MySQL-LOCATE和FIND_IN_SET函数
  18. 【原创】常用元器件(电阻)选型之阻值有多少-cayden20220910
  19. java中的BigInteger(很好很强大)(转)
  20. 合泰单片机做电压表_合泰单片机使用总结

热门文章

  1. 舌苔发白是什么原因造成的?
  2. iOS-通俗易懂的微信支付接入和爬坑指南,十分钟轻松搞完
  3. 使用gensim.models.Word2Vec.load(‘model.txt‘)报错,导致模型加载不了的解决办法之一
  4. win10分屏设置一边竖屏_win10系统电脑屏幕竖屏改为横屏的详细办法
  5. Android Camera HAL3 - 框架流程预览
  6. 网络安全规范(范例)
  7. 最全zabbix安装部署
  8. android手机照片传苹果电脑版,为知笔记Android/iPhone客户端图片传到电脑客户端的方法介绍...
  9. 最快求素数(质数)详解
  10. python opencv图像二值化函数_python opencv 二值化 计算白色像素点的实例