• AQS


    更多干货尽在 一行一行源码分析清楚AbstractQueuedSynchronizer

    一. 概述

    • 为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量、事件,等等)提供一个框架。
    • 此类的设计目标是成为依靠单个原子 int 值来表示状态的大多数同步器的一个有用基础。
    • 子类必须定义更改此状态的受保护方法,并定义哪种状态对于此对象意味着被获取或被释放。假定这些条件之后,此类中的其他方法就可以实现所有排队和阻塞机制。

    1.1 使用

      为了将此类用作同步器的基础,需要适当地重新定义以下方法:

    1.2 AQS基本属性

    public abstract class AbstractQueuedSynchronizer 
                extends AbstractOwnableSynchronizer
                    implements java.io.Serializable {
    
        private static final long serialVersionUID = 7373984972572414691L;
        
        // 头节点,表示当前持有锁的线程
        private transient volatile Node head;
        
        // 阻塞队列的尾节点,每个新的节点进来,都插入到最后,也就形成了一个隐视的链表
        private transient volatile Node tail;
        
        // 代表当前锁的状态,
        // 0代表没有被占用,
        // 大于0代表有线程持有当前锁,之所以说大于0,而不是等于1,是因为锁可以重入嘛,每次重入都加上1
        private volatile int state;
        
        // 代表当前持有独占锁的线程,举个最重要的使用例子,因为锁可以重入.reentrantLock.lock()可以嵌套调用多次
        // 所以每次用下面这个条件来判断当前线程是否已经拥有了锁
        // if (currentThread == getExclusiveOwnerThread()) {state++}
        private transient Thread exclusiveOwnerThread; //继承自AbstractOwnableSynchronizer
        
    }

     1.3 阻塞队列

       AbstractQueuedSynchronizer 的等待队列示意如下所示,注意了,之后分析过程中所说的 queue,也就是阻塞队列不包含 head,不包含 head,不包含 head

      

      等待队列中每个线程被包装成一个 node,数据结构是链表

    static final class Node {
            
            // 标识节点当前在共享模式下
            static final Node SHARED = new Node();
            
            // 标识节点当前在独占模式下
            static final Node EXCLUSIVE = null;
    
            // ======== 下面的几个int常量是给waitStatus用的 ===========
            // 代码此线程取消了争抢这个锁
            static final int CANCELLED =  1;
    
            // 官方的描述是,其表示当前node的后继节点对应的线程需要被唤醒
            static final int SIGNAL    = -1;
    
            // 表示在条件队列中
            static final int CONDITION = -2;
    
            // 同样的不分析,略过吧
            static final int PROPAGATE = -3;
            // =====================================================
    
            // 取值为上面的1、-1、-2、-3,或者0(以后会讲到)
            // 这么理解,暂时只需要知道如果这个值 大于0 代表此线程取消了等待,
            // 也许就是说半天抢不到锁,不抢了,ReentrantLock是可以指定timeouot的。。。
            volatile int waitStatus;
            
            // 前驱节点的引用
            volatile Node prev;
            
            // 后继节点的引用
            volatile Node next;
            
            // 这个就是线程本尊
            volatile Thread thread;
    
        }
  • 相关阅读:
    Linux命令-查看进程
    Linux命令-查看内存
    Linux命令---vim
    oracle分页查询按日期排序失败问题
    oracle使用between and边界问题
    给大家介绍一个自我感觉好用的网站
    想学习一下微服务
    oracle获取年、月、日
    mybatis返回map结果集
    修改表中列
  • 原文地址:https://www.cnblogs.com/virgosnail/p/9446130.html
Copyright © 2020-2023  润新知