Java多线程深入学习-AbstractQueuedSynchronizer框架源码解析

AbstractQueuedSynchronizer

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

1.锁持有者管理AbstractOwnableSynchronizer

/**
 * 锁持有者管理器 抽象类 -- 设置 和 获取独占锁的拥有者线程
 */
public abstract class AbstractOwnableSynchronizer implements java.io.Serializable {

    private static final long serialVersionUID = 3737899427754241961L;

    protected AbstractOwnableSynchronizer() { }

    /** 锁持有者的线程 */
    private transient Thread exclusiveOwnerThread;

    /**
     * 设置锁持有者的线程
     * @param thread
     */
    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }
    /**
     * 获取锁持有者的线程
     */
    protected final Thread getExclusiveOwnerThread() {
        return exclusiveOwnerThread;
    }
}

2.阻塞队列里的节点定义AbstractQueuedSynchronizer.Node

    /** 阻塞队列里的节点定义 */
    static final class Node {
        static final Node SHARED = new Node();	//共享状态
        static final Node EXCLUSIVE = null;		//互斥状态
        static final int CANCELLED =  1;		//值为1,被取消的,在等待队列中等待的线程超时或被中断,进入该状态的节点的将不再变化
        static final int SIGNAL    = -1;		//值为-1,当前节点在入队后、进入休眠状态前,应确保将其prev节点类型改为SIGNAL,以便后者取消或释放时将当前节点唤醒
        static final int CONDITION = -2;		//值为-2,该节点处于条件队列中,当其他线程调用了Condition的signal()方法后,节点转移到AQS的等待队列中,特别要注意的是,条件队列和AQS的等待队列并不是一回事
        static final int PROPAGATE = -3;		//WaistStand值指示下一个获取应该无条件传播
        /** WaistStand值为0这里没写,为0也算是一种状态,但不是上面所有的,表示没有被任何锁拥有 */
        volatile int waitStatus;	//等待状态
        volatile Node prev;			//前一个node
        volatile Node next;			//后一个node
        volatile Thread thread;		//在node里面的线程
        Node nextWaiter;			//下一个正处在等待条件的node
        /**如果在等待node在共享模式下返回true*/
        final boolean isShared() {
            return nextWaiter == SHARED;
        }
        /**返回前一个node。如果为空返回空指针异常*/
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }
        /** 用于建立初始标记或共享标记 */
        Node() {
        }
        /** 给线程添加等待模型,生成node */
        Node(Thread thread, Node mode) {
            this.nextWaiter = mode;
            this.thread = thread;
        }
        /** 给线程添加等待条件,生成node */
        Node(Thread thread, int waitStatus) {
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

3.CAS实现

    /** 
     * 引入unsafe类 
     * 	通过unsafe.objectFieldOffset获取字段对应的偏移量
     */
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long stateOffset;
    private static final long headOffset;
    private static final long tailOffset;
    private static final long waitStatusOffset;
    private static final long nextOffset;
    static {
        try {
        	/**
        	 * class.getDeclaredField(String fieldName)  获取class中fieldName对应的字段
        	 * unsafe.objectFieldOffset(Field field)	获取字段field在类中对应的地址偏移量
        	 */
            stateOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));	//同步的状态
            headOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));	//等待队列头节点
            tailOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));	//等待队列尾节点
            waitStatusOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("waitStatus"));
            nextOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("next"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    /** 用到CAS进行原子更新。如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。 */
    private final boolean compareAndSetHead(Node update) {	//设置state  null -- update
        return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }
    private final boolean compareAndSetTail(Node expect, Node update) { //设置tail  expect -- update
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }
    private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {//设置waitStatus  expect -- update
        return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
    }
    private static final boolean compareAndSetNext(Node node, Node expect, Node update) {//设置next  expect -- update
        return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
    }

    /** 调用unsafe自选操作将state的值更新  返回是否操作成功 */
    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

4.预留方法待子类实现

    /**
     * 尝试获取锁  待子类实现
     */
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 尝试释放锁  待子类实现
     */
    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 尝试获取共享资源   待子类实现  返回负数未失败  其他为成功
     */
    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 共享模式尝试释放锁
     */
    protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * 在独占模式下,状态是否被占用
     */
    protected boolean isHeldExclusively() {
        throw new UnsupportedOperationException();
    }

5.acquire

    /**
     * 获取独占锁,对中断不敏感。
     * 首先尝试获取一次锁,如果成功,则返回;
     * 否则会把当前线程包装成Node插入到队列中,在队列中会检测是否为head的直接后继,并尝试获取锁,
     * 如果获取失败,则会通过LockSupport阻塞当前线程,直至被释放锁的线程唤醒或者被中断,随后再次尝试获取锁,如此反复。
     */
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&	//尝试获取锁 --子类实现
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))	//放入队列 尝试获取锁
            selfInterrupt();
    }


    /**
     * 在队列中的节点通过此方法获取锁,对中断不敏感。
     */
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {	//循环操作
                final Node p = node.predecessor();	//获取node的前一个节点
                
                /*检测当前节点前驱是否head,这是尝试试获取锁的资格。
                 * 如果是的话,则调用tryAcquire尝试获取锁,
                 * 成功,则将head置为当前节点。
                 */
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;	//锁获取成功  返回interrupted
                }
                /*如果未成功获取锁则根据前驱节点判断是否要阻塞。
                 * 如果阻塞过程中被中断,则置interrupted标志位为true。
                 * shouldParkAfterFailedAcquire方法在前驱状态不为SIGNAL的情况下都会循环重试获取锁。
                 */
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }



        /**返回前一个node。如果为空返回空指针异常*/
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }
    /** 
     * 设置node到队列的头,去排队,返回当前node,头节点只是一个节点,里面没有线程 
     * 注意:就算你添加的node是全的,进入队头线程就会被置为空 
     */
    private void setHead(Node node) {
        head = node;
        node.thread = null;
        node.prev = null;
    }


    /**
     * 根据前驱节点中的waitStatus来判断是否需要阻塞当前线程。
     */
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)	//前驱节点设置为SIGNAL状态,在释放锁的时候会唤醒后继节点,所以后继节点(也就是当前节点)现在可以阻塞自己。
            return true;
        if (ws > 0) {	//前驱节点状态为取消
        	//向前遍历,更新当前节点的前驱为往前第一个非取消节点。当前线程会之后会再次回到循环并尝试获取锁。
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * 等待状态为0或者PROPAGATE(-3),设置前驱的等待状态为SIGNAL,
             * 并且之后会回到循环再次重试获取锁。
             */
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

    /**
     * 清除线程中断状态
     */
    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }


    /**
     * 该方法实现某个node取消获取锁。
     */
    private void cancelAcquire(Node node) {
        if (node == null)
            return;
        node.thread = null;

        // 遍历并更新节点前驱,把node的prev指向前部第一个非取消节点
        Node pred = node.prev;
        while (pred.waitStatus > 0)
            node.prev = pred = pred.prev;
        // 记录pred节点的后继为predNext,后续CAS会用到。
        Node predNext = pred.next;
        // 直接把当前节点的等待状态置为取消,后继节点即便也在cancel可以跨越node节点
        node.waitStatus = Node.CANCELLED;

        /**
         * 如果CAS将tail从node置为pred节点了
         * 则剩下要做的事情就是尝试用CAS将pred节点的next更新为null以彻底切断pred和node的联系。
         * 这样一来就断开了pred与pred的所有后继节点,这些节点由于变得不可达,最终会被回收掉。
         * 由于node没有后继节点,所以这种情况到这里整个cancel就算是处理完毕了。
         * 这里的CAS更新pred的next即使失败了也没关系,说明有其它新入队线程或者其它取消线程更新掉了。
         */
        if (node == tail && compareAndSetTail(node, pred)) {
            compareAndSetNext(pred, predNext, null);
        } else {
        	//如果node还有后继节点,这种情况要做的事情是把pred和后继非取消节点拼起来。
            int ws;
            if (pred != head &&
                ((ws = pred.waitStatus) == Node.SIGNAL ||
                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                pred.thread != null) {
                Node next = node.next;
                /* 
                 * 如果node的后继节点next非取消状态的话,则用CAS尝试把pred的后继置为node的后继节点
                 * 这里if条件为false或者CAS失败都没关系,这说明可能有多个线程在取消,总归会有一个能成功的。
                 */
                if (next != null && next.waitStatus <= 0)
                    compareAndSetNext(pred, predNext, next);
            } else {
            	/*
                 * 这时说明pred == head或者pred状态取消或者pred.thread == null
                 * 在这些情况下为了保证队列的活跃性,需要去唤醒一次后继线程。
                 * 举例来说pred == head完全有可能实际上目前已经没有线程持有锁了,
                 * 自然就不会有释放锁唤醒后继的动作。如果不唤醒后继,队列就挂掉了。
                 * 
                 * 这种情况下看似由于没有更新pred的next的操作,队列中可能会留有一大把的取消节点。
                 * 实际上不要紧,因为后继线程唤醒之后会走一次试获取锁的过程,
                 * 失败的话会走到shouldParkAfterFailedAcquire的逻辑。
                 * 那里面的if中有处理前驱节点如果为取消则维护pred/next,踢掉这些取消节点的逻辑。
                 */
                unparkSuccessor(node);
            }
            /*
             * 取消节点的next之所以设置为自己本身而不是null,
             * 是为了方便AQS中Condition部分的isOnSyncQueue方法,
             * 判断一个原先属于条件队列的节点是否转移到了同步队列。
             *
             * 因为同步队列中会用到节点的next域,取消节点的next也有值的话,
             * 可以断言next域有值的节点一定在同步队列上。
             *
             * 在GC层面,和设置为null具有相同的效果。
             */
            node.next = node; // help GC
        }
    }

6.acquireInterruptibly

    /**
     * 以独占方式获得,如果中断,中止。 首先检查中断状态
     */
    public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())	//若线程已被中断  抛出异常
            throw new InterruptedException();
        if (!tryAcquire(arg))	//尝试获取锁
            doAcquireInterruptibly(arg);	//获取锁失败操作  线程排队
    }

    /**
     * 独占模式  线程排队 循环获取锁 会响应中断
     */
    private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.EXCLUSIVE);	//新建节点放入队列
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();	//获取前一个节点
                if (p == head && tryAcquire(arg)) {	//调用tryAcquire(int)直到成功或线程中断
                    setHead(node);	//获取锁成功node设置为头节点  清空信息
                    p.next = null;
                    failed = false;	//设置取消设置标识为false
                    return;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&	//是否需要阻塞当前线程
                    parkAndCheckInterrupt())	//获取线程中断状态并清除中断状态
                    throw new InterruptedException();	//当前线程需要阻塞 但却已经中断  抛出异常结束循环
            }
        } finally {
            if (failed)	//是否取消获取锁
                cancelAcquire(node);	//线程中断  取消获取锁
        }
    }

7.tryAcquireNanos

    /**
     * 尝试以独占模式获取,如果中断则中止,如果给定的超时时间失败
     */
    public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquire(arg) ||
            doAcquireNanos(arg, nanosTimeout);
    }

    /**
     * 处理方式同doAcquireInterruptibly 多限制了等待时长
     */
    private boolean doAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)
            return false;
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }
                nanosTimeout = deadline - System.nanoTime();
                if (nanosTimeout <= 0L)	//是否超时
                    return false;
                if (shouldParkAfterFailedAcquire(p, node) &&
                    nanosTimeout > spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if (Thread.interrupted())
                    throw new InterruptedException();	//响应中断
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

8.acquireShared

    /**
     * 共享模式获取锁
     */
    public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)	//未获取成功
            doAcquireShared(arg);
    }

    /**
     * 共享模式  线程排队 循环获取锁 对中断不敏感
     */
    private void doAcquireShared(int arg) {
        final Node node = addWaiter(Node.SHARED);	//添加节点
        boolean failed = true;	//是否进行取消锁操作
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();	//获取前一个节点
                if (p == head) {
                    int r = tryAcquireShared(arg);	//尝试获取锁
                    if (r >= 0) {	//获取成功
                        setHeadAndPropagate(node, r);
                        p.next = null; 
                        if (interrupted)	//是否要中断
                            selfInterrupt();	//中断当前线程
                        failed = false;	//不需要取消获取锁
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&//是否需要阻塞当前线程
                    parkAndCheckInterrupt())		//获取线程中断状态并清除中断状态
                    interrupted = true;	//设置中断为false
            }
        } finally {
            if (failed)
                cancelAcquire(node);//线程中断  取消获取锁
        }
    }

9.acquireSharedInterruptibly

    /**
     * 以共享方式获取,如果中断,中止。首先检查中断状态
     */
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())//若线程已被中断  抛出异常
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)	//尝试获取资源
            doAcquireSharedInterruptibly(arg);
    }

    /**
     * 共享模式  线程排队 循环获取锁 会响应中断
     * 		与doAcquireShared区别 就是发现中断直接抛出异常跳出循环
     */
    private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

10.tryAcquireSharedNanos

    /**
     * 尝试以共享模式获取,如果中断则中止,如果给定的时间超过,则失败
     */
    public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquireShared(arg) >= 0 ||
            doAcquireSharedNanos(arg, nanosTimeout);
    }


    /**
     * 同上  添加时间限制
     */
    private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)
            return false;
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return true;
                    }
                }
                nanosTimeout = deadline - System.nanoTime();
                if (nanosTimeout <= 0L)
                    return false;
                if (shouldParkAfterFailedAcquire(p, node) &&
                    nanosTimeout > spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

11.releaseShared

    /**
     * 共享模式  释放资源并唤醒等待中的队列
     */
    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {	//尝试释放资源
            doReleaseShared();	
            return true;
        }
        return false;
    }

    /**
     * 释放共享模式,从头部开始的第一个需要信号(被唤醒)的node释放,确保传播。
     * 注意:对于互斥模式,如果需要被唤醒,相当于调用unpackSuccessor()的头部
     */
    private void doReleaseShared() {
        for (;;) {
            Node h = head;
            if (h != null && h != tail) {
                int ws = h.waitStatus;
                if (ws == Node.SIGNAL) {
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                        continue;            // loop to recheck cases
                    unparkSuccessor(h);
                }
                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue;                // loop on failed CAS
            }
            if (h == head)                   // loop if head changed
                break;
        }
    }

12.LockSupport

/**
 * LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞或唤醒
 */
@SuppressWarnings("unused")
public class LockSupport {
    private LockSupport() {} // Cannot be instantiated.

    private static void setBlocker(Thread t, Object arg) {
        UNSAFE.putObject(t, parkBlockerOffset, arg);
    }
    /** 恢复当前线程 */
    public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }
    /** 暂停当前线程 */
    public static void park() {
        UNSAFE.park(false, 0L);
    }
    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }
    
    /** 暂停当前线程,不过有超时时间的限制 */
    public static void parkNanos(long nanos) {
        if (nanos > 0)
            UNSAFE.park(false, nanos);
    }
    public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            UNSAFE.park(false, nanos);
            setBlocker(t, null);
        }
    }
    
    /** 暂停当前线程,直到某个时间 */
    public static void parkUntil(long deadline) {
        UNSAFE.park(true, deadline);
    }
    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }

    public static Object getBlocker(Thread t) {
        if (t == null)
            throw new NullPointerException();
        return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
    }


    static final int nextSecondarySeed() {
        int r;
        Thread t = Thread.currentThread();
        if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
            r ^= r << 13;   // xorshift
            r ^= r >>> 17;
            r ^= r << 5;
        }
        else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
            r = 1; // avoid zero
        UNSAFE.putInt(t, SECONDARY, r);
        return r;
    }

    private static final sun.misc.Unsafe UNSAFE;
    private static final long parkBlockerOffset;
    private static final long SEED;
	private static final long PROBE;
    private static final long SECONDARY;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> tk = Thread.class;
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));
            SEED = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSeed"));
            PROBE = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomProbe"));
            SECONDARY = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
        } catch (Exception ex) { throw new Error(ex); }
    }

}

猜你喜欢

转载自blog.csdn.net/luo_mu_hpu/article/details/107661316