本来准备写一篇AQS的完成解析,已经写了大部分了,但是觉得写得实在太乱了,而且很多细节的东西很难讲清楚,所以还是决定先写一些前文,都是属于AQS整体的一部分,也都是AQS的灵魂组件,所以单拎出来说一下。
本文先争取将贯穿AQS的一个组件先讲清楚。好了,直接进入本文的主题,AQS的内部类--Node
(一) Node是什么,为什么这么重要
Node是AQS中的一个静态的内部类,之所以说贯穿了AQS的整个实现是因为AQS是一个竞争锁的并发框架, 有竞争就会有失败,所以所有的失败的节点都会以Node的形式,等待在等待者队列中,知道放弃竞争了,或者竞争成功。
构建Node的时候都需要两个参数,一个是Thread,标识是哪个线程在等待,那当轮到你竞争的时候也会知道去唤醒哪个Thread进行工作,还有一个是Node.mode,这个是Node内部实现的标识当前Node是数据哪种竞争模式的,有两种不同的模式,独占模式(exclusive)和共享模式(Shared)
独占模式:资源是独占的,一次只能一个线程获取。
共享模式:同时可以被多个线程获取,具体的资源的个数可以通过参数指定。
直接看一下Node的代码
static final class Node {
//标识为共享模式
static final Node SHARED = new Node();
//标识为独占模式
static final Node EXCLUSIVE = null;
/**
* 以下四个都是Node的状态
/
// 标识当前Node取消了竞争
static final int CANCELLED = 1;
// 表示Node的后继结点可以被唤醒了
static final int SIGNAL = -1;
// 表示现在Node阻塞者等待某些条件满足
static final int CONDITION = -2;
// #TODO
static final int PROPAGATE = -3;
volatile int waitStatus;
// 在等待队列中的前一个节点
volatile Node prev;
// 在等待队列中的后一个节点
volatile Node next;
// 执行的线程
volatile Thread thread;
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
Node() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
// 等待队列中的首节点
private transient volatile Node tail;
// 等待队列中的尾节点
private transient volatile Node head;
所以,根据定义我们可以画出AQS中等待者队列的模型
(二) Node的用处
在本系列的后面的文章中,我们会讲到,跟Node的模式分配一样,抢占资源也会有独占式和共享式的方法入口,AQS也留了供用户自定义的抢占逻辑方法。所以Node在整个框架中哪里用到呢?我们可以先自己想一下,如果自己设计一个最简单的抢占模型会怎么设计?肯定会有下面几个步骤
1: 提供一个资源供大家抢占,假设初始状态为1,被占用后设置为0.所以假设有多个线程去获取这个资源的时候,肯定会只有一个线程能抢占成功,那么其他的线程必须按序排好。同时也要考虑到多个节点往队伍中排会出现的并发问题
2: 当上一个节点消费完成后,要将资源释放出来,然后要通知排在队伍中的第一个节点,通知他可以开始竞争资源了。
在AQS框架中,大致的逻辑和我们想的差不多,而Node在其中扮演的就是作为在等待队伍中排队的节点的角色。然后节点中维护了前后节点的指针,所以可以在资源使用结束后通知排在后面的节点开始抢占。
分享到:
相关推荐
Java 并发编程中的 JUC(java.util.concurrent)库以及其核心组件 AQS(AbstractQueuedSynchronizer)在构建高性能、可伸缩性的多线程应用方面具有重要的地位。 AQS 是 JUC 中的核心组件,它提供了一个框架,让...
自己学习过程对Java JUC包知识的总结,看完并理解基本能应付各种基本的问题点,墙裂推荐分享 博客跳转链接: https://blog.csdn.net/qq_35642036/article/details/82767070
【小家java】JUC并发编程之:虚假唤醒以及推荐的解决方案.docx
Java 多线程与并发(10_26)-JUC锁_ 锁核心类AQS详解
juc 的aqs介绍。
java之JUC系列.pdf
1、Java并发体系-第一阶段-多线程基础知识 2、Java并发体系-第二阶段-锁与同步-[1] 3、Java并发体系-第二阶段-锁与同步-[2] 4、Java并发体系-第二阶段-锁与同步-[3] 5、Java并发包-第三阶段-JUC并发包-[1] 6、...
java8 源码 #juc多线程 java.util.concurrent(并发) ##概念复习 进程:正在进行中的程序 线程:进程当中的一个执行单元 关系: 进程包含线程 面试问题: 日常使用进程/线程的案例或者case ###线程的各种状态: Thread....
AQS源码分析一、锁的介绍1.1 乐观锁/悲观锁1.2 共享锁/独占锁1.3 公平锁/非公平锁1.4 小结二、AQS框架结构介绍2.1 类图2.2 AQS数据结构三、源码详解3.1 acquire源码详解3.2 release源码详解四、从ReentranLock看公平...
JUC(java.util.concurrent)库是 Java 标准库的一部分,提供了丰富的多线程并发工具,旨在帮助开发者编写高性能、高可伸缩性的并发程序。下面综合介绍 JUC 库的几个核心概念以及它们在并发编程中的重要性。 1. ...
Java基础之JUC学习!!!
Java后端开发,JUC并发编程Java后端开发,JUC并发编程Java后端开发,JUC并发编程Java后端开发,JUC并发编程Java后端开发,JUC并发编程Java后端开发,JUC并发编程Java后端开发,JUC并发编程Java后端开发,JUC并发编程...
java并发包详解,condition重入锁;Semaphore信号量;ReadWriteLock读写锁;CountDownLatch计时器;CyclicBarrier循环栅栏; 重⼊锁可以完全替代synchronized关键字。在JDK5.0的早期版本中,重⼊锁的性能远远好于 ...
java8 源码 Java基础实战教程 模块 说明 dive-in-concurrent 并发相关实战教程 dive-in-design-pattern 设计模式相关实战教程 dive-in-interview Java面试相关 dive-in-io IO/NIO/AIO相关 dive-in-java8 Java8新特性...
教程视频:在 Java 5.0 提供了 java.util.concurrent(简称JUC)包,在此包中增加了在并发编程中很常用的工具类, 用于定义类似于线程的自定义子系统,包括线程池,异步 IO 和轻量级任务框架;还提供了设计用于多线程上下文...
课程内容包括了JAVA手写线程池,UC线程池API详解,线程安全根因详解,锁与原子类,分布式锁原理与实现方式,并发编程-AQS等等针对性非常强的JAVA编程开发教程,这其中的内容对JAVA开发技能的拔尖,非常的有帮助。...
本资源描述了Java并发常见的问题AQS的加锁解锁的过程
Java虚拟机中并没有严格规定synchronized需要如何实现,只要能满足锁住一个对象,一个一个线程的去执行其中的代码块即可。 sync(Object)锁住一个对象,这时会markWord,记录这个线程的ID,这时只有一个线程来,其实...
从JUC中的AQS引入,讲解Java volatile与AQS锁内存可见性
用于定义类似于线程的自定义子系统,包括线程池,异步 IO 和轻量级任务框架;包含下载地址