概要

AQS维护了一个同步队列

Condition是JUC的一个接口,AQS的ConditionObject实现了这个接口,维护了一个等待队列(等待signal信号的队列)

线程调用reentrantLock.lock()时,线程被加入到AQS同步队列中;

线程A调用condition.await()方法时,线程A从AQS同步队列中被移除,被加入到Condition等待队列,等待signal信号

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

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

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

例子分析参见另一篇文章:【JUC】Condition和生产者消费者模型  https://www.cnblogs.com/twoheads/p/9591874.html

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

说明:AbstractQueuedSynchronizer类底层的数据结构是使用链表,是队列的一种实现,故也可看成是队列,其中Sync queue,即同步队列,是双向链表,包括head结点和tail结点,head结点主要用作后续的调度。而Condition queue即等待队列不是必须的,其是一个单向链表,只有当使用Condition时,才会存在此单向链表。并且可能会有多个Condition queue。Condition的具体实现类是AQS的内部类ConditionObject

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

而Condition自己也维护了一个等待队列(等待signal信号的队列),两个队列的作用是不同,事实上,每个线程也仅仅会同时存在以上两个队列中的一个

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

    //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等待队列,因为线程需要signal信号。
  3. 线程B(节点B)由于线程A(节点A)释放锁被唤醒,判断成为同步队列头结点且同步状态为0可以获取锁;线程B(节点B)获取锁。

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

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

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

转:

https://blog.csdn.net/tb3039450/article/details/69056169

http://ifeve.com/understand-condition/

AbstractQueuedSynchronizer同步队列与Condition等待队列协同机制的更多相关文章

  1. Java并发包源码学习系列:CLH同步队列及同步资源获取与释放

    目录 本篇学习目标 CLH队列的结构 资源获取 入队Node addWaiter(Node mode) 不断尝试Node enq(final Node node) boolean acquireQue ...

  2. 学习JUC源码(3)——Condition等待队列(源码分析结合图文理解)

    前言 在Java多线程中的wait/notify通信模式结尾就已经介绍过,Java线程之间有两种种等待/通知模式,在那篇博文中是利用Object监视器的方法(wait(),notify().notif ...

  3. Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理

    Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...

  4. Java并发编程3-抽象同步队列AQS详解

    AQS是AtractQueuedSynchronizer(队列同步器)的简写,是用来构建锁或其他同步组件的基础框架.主要通过一个int类型的state来表示同步状态,内部有一个FIFO的同步队列来实现 ...

  5. Java并发包之同步队列SynchronousQueue理解

    1 简介 SynchronousQueue是这样一种阻塞队列,其中每个put必须等待一个take,反之亦然.同步队列没有任何内部容量,甚至连一个队列的容量都没有.不能在同步队列上进行peek,因为仅在 ...

  6. 【转载】阻塞队列之三:SynchronousQueue同步队列 阻塞算法的3种实现

    一.SynchronousQueue简介 Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除 ...

  7. 【死磕Java并发】-----J.U.C之AQS:CLH同步队列

    此篇博客全部源代码均来自JDK 1.8 在上篇博客[死磕Java并发]-–J.U.C之AQS:AQS简单介绍中提到了AQS内部维护着一个FIFO队列,该队列就是CLH同步队列. CLH同步队列是一个F ...

  8. 阻塞队列之三:SynchronousQueue同步队列 阻塞算法的3种实现

    一.SynchronousQueue简介 Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除 ...

  9. CLH同步队列

    原文链接:https://blog.csdn.net/chenssy/article/details/60781148 AQS内部维护着一个FIFO队列,该队列就是CLH同步队列. CLH同步队列是一 ...

随机推荐

  1. SpringMvc常见问题汇总

    1.Service类未用@Service注解2016-10-26 17:31:36 [org.springframework.web.context.ContextLoader]-[ERROR] Co ...

  2. Appium学习笔记2_Android获取元素篇

    在利用Appium做自动化测试时,最重要的一步就是获取对应的元素值,根据元素来对对象进行对应的操作,如果获得对象元素呢? Appium Server Console其实提供了一个界面对话框" ...

  3. SQLSERVER最简单的同名数据库恢复过程.

    一. 冷备份恢复 1. net stop mssqlserver # 如果是安装的默认数据库实例 关闭 sqlserver的数据库 2. copy sqlserver的数据文件 主要是mdf 数据文件 ...

  4. [转帖]简析数据中心三大Overlay技术

    简析数据中心三大Overlay技术 http://www.jifang360.com/news/20161010/n225987768.html 搭建大规模的云计算环境需要数据中心突破多种技术难题,其 ...

  5. [日常工作]WorkStation 使用端口转发的方式使用宿主机IP地址提供服务

    1. 虚拟机内的地址如果经常变化,或者是想使用宿主机进行网络服务 但是又不想有人能够访问具体的服务器提供机器.. 可以使用宿主机转发虚拟机的端口的方式来进行处理. workstation 比较好实现 ...

  6. Smarty 变量修饰器

    为了更方便的实现 功能与显示分离,通常会用 smarty 将功能代码中的数据 assign 到页面中,在页面中合理使用 smarty 的修饰方法,会使页面显示更美观! 一个数据可同时使用多个修饰函数, ...

  7. 无法获得锁 /var/lib/dpkg/lock

    sudo rm /var/cache/apt/archives/lock sudo rm /var/lib/dpkg/lock

  8. 深入浅出——float

    FLOAT  参考张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]的CSS float浮动的深入研究.详解及拓展 1.FLOAT的特性 float属性的初衷只是为了实现文字 ...

  9. as_matrix、保存训练模型

    #-*- coding: utf-8 -*- #构建并测试CART决策树模型 import pandas as pd #导入数据分析库 from random import shuffle #导入随机 ...

  10. apache2.4.29安装脚本

    #!/bin/bash . /etc/init.d/functions yum install -y expat-devel gcc gcc-c++ zlib-devel openssl-devel ...