AQS的不公平锁源码

同步器节点的waitStatus解释
CANCELLED 取消状态

SIGNAL -1 等待触发状态,前节点可能是head或者前节点为取消状态CANCELLED

CONDITION -2 等待条件状态,在等待队列中

PROPAGATE -3 状态需要向后传播


//不公平锁的lock函数
static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            //首先尝试获得锁,如果获得,就将独占锁的内部变量改为当前线程
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
            //如果没有获得锁,就转到AQS类的acquire函数中
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
}

//AQS类的acquire函数,传入参数1
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&         //查看是否能够获得锁,就是上面的NonfairSync上面的tryAcquire方法,这个方法重写了虚类方法,如果不能,将返回false,查看&&后的方法
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
}

//ReentrantLock类的nonfairTryAcquire函数
 final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();      
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {      //尝试获得锁,如果成功了就进去执行,这个也体现了不公平锁的机制
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {        //如果没有成功,锁是被自己占住的,那就可以进入,体现了可重入的机制
                int nextc = c + acquires;                           //计数器加一
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;                       //这个时候的情况就是锁是被别的线程占领的
}

//AQS类的addWaiter函数,传入参数Node.EXCLUSIVE
private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // 用快速入列法试验一下
        Node pred = tail;           
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {        //cas操作设置尾节点
                pred.next = node;
                return node;
            }
        }
        enq(node);          //当cas操作不成,或者队列中没有别的线程的时候用这个
        return node;
}
//AQS类的enq函数,传入参数等待假如阻塞队列的线程
private Node enq(final Node node) {
    //死循环,不加入不出来
        for (;;) {  
            Node t = tail;      //获取尾节点
            if (t == null) { // 如果尾节点是空,说明这个是第一个阻塞线程
                if (compareAndSetHead(new Node()))  //设置阻塞线程的头部,一个没有任何用处的头部
                    tail = head;                    //尾巴就是头,然后再次循环
            } else {                                
                node.prev = t;                      
                if (compareAndSetTail(t, node)) {      //cas操作将新的线程插入到tail,如果不成功将会再次循环过来
                    t.next = node;
                    return t;                           //这个返回值在addWaiter函数中没有用
                }
            }
        }
}


//通过调用addWaiter函数,AQS将当前线程加入到了等待队列,但是还没有阻塞当前线程的执行,接下来我们就来分析一下acquireQueued函数.
//AQS类的acquireQueued函数,传入参数是已经加入到队列中的新的node节点
final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {         //如果新插入的这个节点是head节点的后面节点,说明新来的节点是将要获取锁的线程,尝试去获取锁
                    setHead(node);                          //将自己设置为头节点
                    p.next = null; // help GC               //原来的节点next置空
                    failed = false;
                    return interrupted;             //因为没有被中断所以返回false
                }
                if (shouldParkAfterFailedAcquire(p, node) &&    //判断是否要进入阻塞状态.如果`shouldParkAfterFailedAcquire`返回true,表示需要进入阻塞
                    parkAndCheckInterrupt())                    ////调用parkAndCheckInterrupt挂起线程,等待被唤醒             
                    interrupted = true;             
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
}

//前面我们已经说过只有前一个节点pred的线程状态为SIGNAL时,当前节点的线程才能被挂起。
 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             *前一个节点正在等待锁的释放,所以这个新的节点要阻塞
             */
            return true;
        if (ws > 0) {
            /*
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             * 前一个节点处于取消获取独占性变量的状态,所以,可以跳过去,返回false
             */
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don't park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             */
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
 }

 

posted @ 2018-11-23 21:23  式微胡不归  阅读(461)  评论(0编辑  收藏  举报