AbstractQueuedSynchronizer 原理解析(下)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: AbstractQueuedSynchronizer 原理解析

Semaphore


image.png


深入理解


  • 锁, 面向锁的使用者, 核心是定义了程序和锁的交互 API


  • 同步器,面向锁的实现者, 比如 Java 并发大神 Doug Lee , 提出同一规范并且简化了锁的实现,屏蔽了同步状态管理、阻塞线程排队和通知、唤醒机制等。


AQS 作用


加锁会导致阻塞


有阻塞就需要排队,实现排队必然需要某种形式的队列来进行管理。


解释说明


抢到资源的线程直接使用处理业务逻辑,抢不到资源的必然进入一种排队等候机制。抢占资源失败的线程去等待(类似银行业务遍历窗口都满了,暂时没有受理窗口的顾客只能去候客区排队等候),但等待线程仍然保持获取锁的可能且获取锁流程仍在继续(候客区的顾客也在等待着叫号,轮到了再去受理窗口办理业务)。


既然提到了排队等候机制。 那么就一定会有某种队列形成,这样的队列是什么数据结构呢?


如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁的分配。这个机制主要是通过 CHL 队列的变体来实现的,将暂时获取不到的锁的线程加入到队列中,这个队列就是 AQS 的抽象实现。它将请求共享资源的线程封装成队列的节点 Node , 通过 CAS , 自旋以及 LockSupport.park() 的方式,维护 sate 变量的状态,使并发达到同步的控制效果。


image.png


AQS 实践


AQS 初步认识


image.png


有阻塞就需要有排队,实现排队必须需要队列


AQS 使用一个 volatile 的 int 类型的成员变量来表示同步状态,通过内置的 FIFO 队列来完成资源获取的排队工作将每条要去抢占资源的线程封装成一个 Node 节点来实现锁的分配,通过 CAS 完成对 State 值的修改。


image.png


AQS 内部体系架构


image.png


AQS 组成


  • AQS 的 int 变量


AQS 同步状态 State 成员变量


/**
     * The synchronization state.
     */
    private volatile int state;


银行办理业务的受理窗口状态


1、0 就是没人, 自由状态可以办理


2、大于等于 1 , 有人占用窗口,等着去


  • AQS 的 CLH 队列


CLH 队列(三个大牛的名字组成),为一个双向队列


image.png


银行候客区的等待顾客


  • 小总结


有阻塞就需要排队,实现排队必然需要队列


state + CLH 变种的双端队列


AQS 同步队列的基本结构


  • Node 中的 int 变量


Node 的等待状态 waitState 成员变量


volatile int waitStatus;


总结一下


等候区其他顾客(其他线程)的等待状态


队列中每个排队的个体就是一个 Node


  • Node 类的详解


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;
    // 等待 condition 唤醒
        static final int CONDITION = -2;
    // 共享式同步状态获取将会无条件的传播下去
        static final int PROPAGATE = -3;
        // 初始状态为 0 , 状态式上面的几种
        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();
            else
                return p;
        }
        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;
        }
    }


AQS 同步队列的基本结构


image.png


相关文章
|
12天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
30 3
|
5天前
|
数据采集 存储 编解码
一份简明的 Base64 原理解析
Base64 编码器的原理,其实很简单,花一点点时间学会它,你就又消除了一个知识盲点。
26 3
|
24天前
|
前端开发 Java 应用服务中间件
21张图解析Tomcat运行原理与架构全貌
【10月更文挑战第2天】本文通过21张图详细解析了Tomcat的运行原理与架构。Tomcat作为Java Web开发中最流行的Web服务器之一,其架构设计精妙。文章首先介绍了Tomcat的基本组件:Connector(连接器)负责网络通信,Container(容器)处理业务逻辑。连接器内部包括EndPoint、Processor和Adapter等组件,分别处理通信、协议解析和请求封装。容器采用多级结构(Engine、Host、Context、Wrapper),并通过Mapper组件进行请求路由。文章还探讨了Tomcat的生命周期管理、启动与停止机制,并通过源码分析展示了请求处理流程。
|
21天前
|
开发框架 缓存 前端开发
electron-builder 解析:你了解其背后的构建原理吗?
本文首发于微信公众号“前端徐徐”,详细解析了 electron-builder 的工作原理。electron-builder 是一个专为整合前端项目与 Electron 应用的打包工具,负责管理依赖、生成配置文件及多平台构建。文章介绍了前端项目的构建流程、配置信息收集、依赖处理、asar 打包、附加资源准备、Electron 打包、代码签名、资源压缩、卸载程序生成、安装程序生成及最终安装包输出等环节。通过剖析 electron-builder 的原理,帮助开发者更好地理解和掌握跨端桌面应用的构建流程。
49 2
|
2天前
|
供应链 安全 分布式数据库
探索区块链技术:从原理到应用的全面解析
【10月更文挑战第22天】 本文旨在深入浅出地探讨区块链技术,一种近年来引起广泛关注的分布式账本技术。我们将从区块链的基本概念入手,逐步深入到其工作原理、关键技术特点以及在金融、供应链管理等多个领域的实际应用案例。通过这篇文章,读者不仅能够理解区块链技术的核心价值和潜力,还能获得关于如何评估和选择适合自己需求的区块链解决方案的实用建议。
8 0
|
13天前
|
前端开发 JavaScript UED
axios取消请求CancelToken的原理解析及用法示例
axios取消请求CancelToken的原理解析及用法示例
47 0
|
16天前
|
存储 缓存 数据处理
深度解析:Hologres分布式存储引擎设计原理及其优化策略
【10月更文挑战第9天】在大数据时代,数据的规模和复杂性不断增加,这对数据库系统提出了更高的要求。传统的单机数据库难以应对海量数据处理的需求,而分布式数据库通过水平扩展提供了更好的解决方案。阿里云推出的Hologres是一个实时交互式分析服务,它结合了OLAP(在线分析处理)与OLTP(在线事务处理)的优势,能够在大规模数据集上提供低延迟的数据查询能力。本文将深入探讨Hologres分布式存储引擎的设计原理,并介绍一些关键的优化策略。
61 0
|
22天前
|
SQL 分布式计算 大数据
大数据-97 Spark 集群 SparkSQL 原理详细解析 Broadcast Shuffle SQL解析过程(一)
大数据-97 Spark 集群 SparkSQL 原理详细解析 Broadcast Shuffle SQL解析过程(一)
33 0
|
22天前
|
SQL 分布式计算 算法
大数据-97 Spark 集群 SparkSQL 原理详细解析 Broadcast Shuffle SQL解析过程(二)
大数据-97 Spark 集群 SparkSQL 原理详细解析 Broadcast Shuffle SQL解析过程(二)
61 0
|
26天前
|
Java C语言 Python
解析Python中的全局解释器锁(GIL):影响、工作原理及解决方案
解析Python中的全局解释器锁(GIL):影响、工作原理及解决方案
31 0

推荐镜像

更多