从Condition开始,回顾AQS

devtools/2024/12/26 16:40:22/

Synchronized和Reentrantlock的挂起逻辑

synchronized中有两个核心的结构

  • EntryList + cxq:等待拿锁的线程存储位置
  • Waitset:被执行wait方法的线程存储位置

流转: 

  • 线程获取锁资源失败,扔到EntryList + cxq
  • 线程持有锁资源,执行了wait方法,扔到WaitSet
  • 其他线程执行了notify/notifyAll方法,WaitSet中的线程会扔到EntryList/cxq中

ReetrantLock中的Condition中支持了类似上述的功能

ReetrantLock中有两个核心的结构

  • AQS的同步队列:等待拿锁的线程存储位置
  • AQS内部的Condition单向链表:被执行await方法的线程存储位置

流转: 

  • 线程获取锁资源失败,扔到同步队列
  • 线程持有锁资源,执行了await方法,扔到Condition单向链表
  • 其他线程执行了signal/signalAll方法,WaitSet中的线程会扔到同步队列中

AQS的Condition支持

 AQS是JUC包下的一个抽象类,单独聊AQS没什么,但是他是AQS很多JUC包下的工具类的父类

AQS有三个核心点:

  • int类型的state属性
  • AQS内部的同步队列
  • Condition的单向链表

本文主要细看Condition单向链表:

java">static final class Node {static final Node SHARED = new Node();static final Node EXCLUSIVE = null;static final int CANCELLED =  1;static final int SIGNAL    = -1;static final int CONDITION = -2;static final int PROPAGATE = -3;/*Node只要在Condition单向链表中,状态就是上面的-2waitStatus简写wt*/volatile int waitStatus;volatile Node prev;volatile Node next;volatile Thread thread;/*单向链表的下一个节点*/Node nextWaiter;final boolean isShared() {return nextWaiter == SHARED;}final Node predecessor() throws NullPointerException {Node p = prev;if (p == null)throw new NullPointerException();elsereturn p;}Node() {    // Used to establish initial head or SHARED marker}Node(Thread thread, Node mode) {     // Used by addWaiterthis.nextWaiter = mode;this.thread = thread;}Node(Thread thread, int waitStatus) { // Used by Conditionthis.waitStatus = waitStatus;this.thread = thread;}
}

  • Condition是基于Node对象组成的单向链表 
  • 在Condition中,Node状态必须是-2,如果不是-2,就可以从中移除掉了
  • Condition的Node是利用nextWaiter属性连接下一个节点
  • Condition中还有指向头尾的两个属性,分别是firstWaiter和lastWaiter

Condition的挂起操作流程

当持有lock锁的线程,执行以下4个流程:

  1. 将当前对象封装成Node对象,加入单向链表中
  2. 释放锁资源
  3. 确认当前线程的Node,没有在AQS的同步队列中。如果在,说明执行了signal方法,那个线程已经进入了同步队列。不需要挂起
  4. 没有在同步队列,直接挂起

 

Condition的signal唤醒操作流程

  1. 确保执行signal的线程持有锁资源
  2. 将第一个Node从单向链表中断开
  3. 将Node的状态从-2改成0
  4. 将Node移到同步队列
  5. 确保Node在同步队列中可以被唤醒。直接唤醒线程和将prev指向的Node状态设置为-1

 

Condition在await被唤醒后的逻辑

1、确认被唤醒的方式:

  • 单纯地被signal方法唤醒
  • 被interrupt中断唤醒
  • 被signal唤醒后,然后执行了interrupt(保留中断标记位)

2、确保Node在同步队列后,就可以跳出while循环

3、执行acquireQueued方法后,等待获取锁资源

4、在获取锁资源的同时,如果被中断过,需要确认是否保留中断标记位

5、如果是中断唤醒,需要将当前Node断开单向链表连接

6、根据中断模型,执行抛出异常、方法


http://www.ppmy.cn/devtools/145570.html

相关文章

网络管理-期末项目(附源码)

环境:网络管理 主机资源监控系统项目搭建 (保姆级教程 建议点赞 收藏)_搭建网络版信息管理系统-CSDN博客 效果图 下面3个文件的项目目录(python3.8.8的虚拟环境) D:\py_siqintu\myproject5\Scripts\mytest.py D:\py_siqintu\myproject5\Sc…

计算机网络习题( 第3章 物理层 第4章 数据链路层 )

第3章 物理层 一、单选题 1、下列选项中,不属于物理层接口规范定义范畴的是( )。 A、 接口形状 B、 引脚功能 C、 传输媒体 D、 信号电平 正确答案: C 2、在物理层接口特性中,用于描述完成每种功能的事件发…

Unity3D Huatuo技术原理剖析详解

前言 在游戏开发领域,Unity3D凭借其强大的跨平台能力和丰富的功能,成为了众多开发者的首选工具。而在Unity3D的生态系统中,Huatuo作为一款重要的插件,为游戏开发带来了极大的便利。本文将深入剖析Huatuo的技术原理,并…

修改npm镜像源

要更改 npm 的镜像源,你可以使用 npm config set registry 命令。以下是一些常见的镜像源: 1. **官方 npm 注册表**: bash npm config set registry https://registry.npmjs.org/ 2. **淘宝 npm 镜像**: bash npm conf…

5G CPE 主控CPU(上位机) 数据转发性能评估--基于5G模组和NEO3开发板评估

5G CPE ARM 主控CPU 数据转发性能评估--基于5G模组和NEO3开发板评估 摘要NEO3介绍演示架构网络拓扑硬件连接固件及驱动NEO固件NEO3串口驱动拔号及网络配置配置AT接口拔号NEO3网络接口性能测试5G空口性能NEO千兆网口性能验证NEO3 高速接口数据转发性能摘要 当前主流CPE多采用集…

机器学习(四)-回归模型评估指标

文章目录 1. 哪个模型更好?2. 线性回归评估指标3. python 实现线性模型评估指标 1. 哪个模型更好? 我们之前已经对房价预测的问题构建了线性模型,并对测试集进行了预测。 如图所示,横坐标是地区人口,纵坐标是房价&am…

从 GitLab.com 到 JihuLab.com 的迁移指南

本文分享从 GitLab.com 到 JihuLab.com 的迁移指南。 近期,GitLab Inc. 针对其 SaaS 产品做了限制,如果被判定为国内用户,则会建议使用其在国内的发布版本极狐GitLab。从 GitLab SaaS 产品(GitLab.com)迁移到极狐GitL…

水库大坝浸润线绘制

先看效果 直接上代码&#xff08;vue环境&#xff09; <template><div id"canvas-continer" class"h100 w100 mt4"><canvas ref"canvas" id"canvas" class"canvas"></canvas></div> <…