• Java源码阅读(五)—— AbstractQueuedSynchronizer


    背景和作用

    在同步组件的实现中,AQS是核心部分,同步组件的实现者通过使用AQS提供的模板方法实现同步组件语义,AQS则实现了对同步状态的管理,以及对阻塞线程进行排队,等待通知等等一些底层的实现处理。AQS的核心也包括了这些方面:同步队列,独占式锁的获取和释放,共享锁的获取和释放以及可中断锁,超时等待锁获取这些特性的实现。

    AQS

    
    public abstract class AbstractOwnableSynchronizer
        implements java.io.Serializable {
    
        /**
         * Empty constructor for use by subclasses.
         */
        protected AbstractOwnableSynchronizer() { }
    
        /**
         * The current owner of exclusive mode synchronization.
         */
        //独占模式下的线程
        private transient Thread exclusiveOwnerThread;
    
        // getter、setter
        protected final void setExclusiveOwnerThread(Thread thread) {
            exclusiveOwnerThread = thread;
        }
    
        protected final Thread getExclusiveOwnerThread() {
            return exclusiveOwnerThread;
        }
    }
    
    
    
    

    AQS#Node

    
            /** Marker to indicate a node is waiting in shared mode */
            static final Node SHARED = new Node();
    
            /** Marker to indicate a node is waiting in exclusive mode */
            static final Node EXCLUSIVE = null;
    
            /** waitStatus value to indicate thread has cancelled */
            static final int CANCELLED =  1;
    
            /** waitStatus value to indicate successor's thread needs unparking */
            static final int SIGNAL    = -1;
    
            /** waitStatus value to indicate thread is waiting on condition */
            static final int CONDITION = -2;
    
            /**
             * waitStatus value to indicate the next acquireShared should
             * unconditionally propagate
             */
            static final int PROPAGATE = -3;
    
            // 该变量主要记录线程的状态,确保线程是有效的,CANCELLED、SIGNAL、CONDITION、PROPAGATE
            volatile int waitStatus;
    
            volatile Node prev;
    
            volatile Node next;
    
            volatile Thread thread;
    
            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;
            }
    
    

    AbstractQueuedSynchronizer

    AQS使用CLH队列来实现线程排队的功能,CLH队列的原理是一个双向链表,每个链表由Node节点组成,Node节点保存prev和next两个指针,并保存指向线程的指针。

    /**
         * Head of the wait queue, lazily initialized.  Except for
         * initialization, it is modified only via method setHead.  Note:
         * If head exists, its waitStatus is guaranteed not to be
         * CANCELLED.
         */
        // 记录CLH的头部节点,目的是配合tail实现出队操作
        private transient volatile Node head;
    
        /**
         * Tail of the wait queue, lazily initialized.  Modified only via
         * method enq to add new wait node.
         */
        // 记录CLH的尾部节点
        private transient volatile Node tail;
    
        /**
         * The synchronization state.
         */
        // 用于记录加锁的次数,同一个线程加两次锁,则state = 2
        private volatile int state;
    
       /**
         * Inserts node into queue, initializing if necessary. See picture above.
         * @param node the node to insert
         * @return node's predecessor
         */
        // 入队操作
        private Node enq(final Node node) {
            for (;;) {
                Node t = tail;
                if (t == null) { // Must initialize
                    if (compareAndSetHead(new Node()))
                        tail = head;
                } else {
                    node.prev = t;
                    if (compareAndSetTail(t, node)) {
                        t.next = node;
                        return t;
                    }
                }
            }
        }
    
  • 相关阅读:
    SVN还原项目到某一版本(转)
    C# Web Service 不使用服务引用直接调用方法(转)
    动态调用webservice时 ServiceDescriptionImporter类在vs2010无法引用的解决方法 (转)
    log4net示例2-日志输入存入Access(转)
    C# log4net 配置及使用详解--日志保存到文件和Access(转)
    未能解析引用的程序集......因为它对不在当前目标框架“.NETFramework,Version=v4.0,Profile=Client”中的 (转)
    Hello log4net——做一个实用好用的log4net的demo(转)
    JS移动客户端--触屏滑动事件
    js生成二维码实例
    触屏版类似刷新页面文本框获取焦点的同时弹出手机键盘的做法
  • 原文地址:https://www.cnblogs.com/fonxian/p/10871862.html
Copyright © 2020-2023  润新知