zoukankan      html  css  js  c++  java
  • 十七、认识AQS

    一、什么是AQS

    1.1 概念

    AbstractQueuedSynchronizer抽象同步队列,其定义了一套多线程访问共享资源的同步器框架,通过内置的FIFO队列来完成资源获取线程的排队工作,并通过一个int类变量表示持有锁的状态。 

    1.2 基石

    很多同步类实现都依赖于AQS,如常用的ReentrantLock、Semaphore、CountDownLatch、ReentrantReadWriteLock等等。

    二、作用

    用于管理加锁导致的阻塞。当多个线程争用资源时,未抢到资源的线程则会进入此队列,在其内部进行管理。

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

    三、AQS内部体系架构

    3.1 AQS自身

    AQS的int变量state:表示锁的占用状态。

    AQS的CLH队列:Node队列。(Craig、Landin and Hagersten 队列,是个单向链表,AQS中的队列是CLH变体的虚拟双向队列(FIFO))

    3.2 内部类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;
        static final int CONDITION = -2;
        static final int PROPAGATE = -3;
     
        /**
         * CANCELLED,值为1,表示当前的线程被取消
         * SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark;
         * CONDITION,值为-2,表示当前节点在等待condition,也就是在condition队列中;
         * PROPAGATE,值为-3,表示当前场景下后续的acquireShared能够得以执行;
         * 值为0,表示当前节点在sync队列中,等待着获取锁。
         */
        volatile int waitStatus;
     
        // 前驱结点
        volatile Node prev;
     
        // 后继结点
        volatile Node next;
     
        // 与该结点绑定的线程
        volatile Thread thread;
     
        // 存储condition队列中的后继节点
        Node nextWaiter;
     
        // 是否为共享模式
        final boolean isShared() {
            return nextWaiter == SHARED;
        }
     
        // 获取前驱结点
        final Node predecessor() throwsNullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }
     
        Node() { // Used to establish initial heador SHARED marker
        }
     
        Node(Thread thread, Node mode) { // Used byaddWaiter
            this.nextWaiter = mode;
            this.thread = thread;
        }
     
        Node(Thread thread, int waitStatus) { //Used by Condition
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }
  • 相关阅读:
    mybatis-plus代码生成模板
    Flask_APScheduler的简单使用
    Linux 配置mysql 远程连接
    ubuntu19.04 安装mysql,没有初始密码,重设初始密码
    ubuntu19.04 配置远程连接ssh
    python3 win 建立虚拟环境(virtualenv)
    python property(不动产)方法
    python,装饰器带参数,原理
    利用python装饰器为字符串添加,HTML标签
    python pymysql 基本使用
  • 原文地址:https://www.cnblogs.com/shiblog/p/15606639.html
Copyright © 2011-2022 走看看