J.U.C 学习【一】AbstractQueuedSynchronizer队列实现和API简介

文章中的源码均来自JDK1.8

一、简介  

    AbstractQueuedSynchronizer(AQS) 是一个队列同步器,可以用来构建锁或者其他同步组件,如 ReentrantLock 等, 它使用一个 int 的成员变量 state 来表示同步状态,通过内置的 FIFO 队列来完成线程想要获取资源时的排队工作。


二、同步队列的实现

   同步队列是使用双向链表来实现的,而链表的节点则是使用一个内部类 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的signal()方法后节点会从等待队列转到同步队列中 */
        static final int CONDITION = -2;
        /**
         * 表示下一次共享式同步状态获取将会无条件地被传播下去
         */
        static final int PROPAGATE = -3;

        /**
         * 等待状态
         */
        volatile int waitStatus;

        /**
         * 前驱节点
         */
        volatile Node prev;

        /**
         * 后继节点
         */
        volatile Node next;

        /**
         * 获取同步状态的线程.
         */
        volatile Thread thread;

        /**
         * 当线程在Condition等待时的后继节点或者用来表示当前节点上共享还是独占
         */
        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;
        }
    }

三、API简介

   同步器的设计是基于模板方法模式的,也就是使用者需要继承同步器并重写其指定的方法,随后将同步器组合到自定义同步组件中,并调用同步器提供的模板方法,而这些模板方法将会调用使用者重写的方法。同步器可重写的方法如下:

  • boolean tryAcquire(int arg) 独占式获取同步状态
  • boolean tryRelease(int arg) 独占式释放同步状态
  • int tryAcquireShared(int arg) 共享式获取同步状态
  • boolean tryReleaseShared(int arg) 共享式释放同步状态
  • boolean isHeldExclusively() 是否被当前线程独占

   使用者除了可重写以上的方法外,还可以通过调用同步器提供的方来是访问或修改同步状态,如下:

  • getState() 获取同步状态
  • setState(int newState) 设置当前同步状态
  • compareAndSetState(int expect, int update) 使用 CAS 设置当前状态

四、CAS 的简单介绍

CAS是一种乐观锁,compare and swap,也就是比较并替换,它的操作包含3个操作数 --- 内存位置(V)、预期原值(A)、新值(B),如果内存位置的值与预期原值相同,则将内存位置的值替换成新值,否则不做任何改变。CAS的原子操作是利用处理器提供的CMPXCHG指令来实现的,它与synchrionized的区别在于CAS是无阻塞的,但是它只能保证一个共享变量的原子操作。其他详细这里不多讲,可自行查找资料。

参考资料:《Java并发编程的艺术》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值