Hello World

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;

    }

 

posted @ 2018-08-08 22:29  小小忧愁米粒大  阅读(152)  评论(0编辑  收藏  举报
瞅啥瞅,好好看书