AQS源碼解析(9)Condition.signal

signal和signalAll大同小異,本節(jié)我們來看下signal函數(shù),signal核心調(diào)用的是doSignal,所以signal函數(shù)就不貼了:

//doSignal只做了一件事,將wait隊列中的節(jié)點移出道aqs的等待隊列中
private void doSignal(Node first) {
            do {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;//這里是個出隊的過程,將對頭從隊列中移出
            } while (!transferForSignal(first) &&
                     (first = firstWaiter) != null);
        }


final boolean transferForSignal(Node node) {
        /*
         * If cannot change waitStatus, the node has been cancelled.
         *  看作者注解,如果不能將waitStatus設置成0,表示該節(jié)點是取消的,返回false
         *  這里有兩種情況:
         *  1)ws的值不是condition(-2),說明已經(jīng)被改變了
         *  2)cas失敗,說明有另一個線程也同時在signal,
         *  不管哪種情況該node一定會被喚醒
         *  這里返回false,看上面函數(shù)的while進入循環(huán),拿到下一個節(jié)點,繼續(xù)
         */
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;

       //入aqs的等待隊列
        Node p = enq(node);
        int ws = p.waitStatus;
        //ws>0說明不是正常等待狀態(tài)(一般是cancel),可以看下面的源碼注解
        //或者cas ws失敗則喚醒node線程
        //注意這里的p是node的前置節(jié)點,假如cas成功,說明前置節(jié)點也是在等待狀態(tài),那么就不需要喚醒node線程(因為前置都在等待,node也一定是等待,等走aqs的正常流程喚醒就好了)
        //如果cas失敗說明ws正在被其他線程修改,這里又有2種情況:
        //1)ws被修改成1(cancel),那么喚醒線程沒問題
        //2)ws被修改成0,也就是p已經(jīng)獲得到鎖,這樣unpark后會讓代碼執(zhí)行到acquireQueued()去cas嘗試獲取鎖,以此來提高效率
        //再看如果ws<=0表示正常等待狀態(tài),不去喚醒線程會不會有問題?
        //那么線程會一直掛起直到被p喚醒,重新進入while (!isOnSyncQueue(node)) 這個時候一定在aqs的等待隊列中,繼續(xù)往下進入acquireQueued()去獲取鎖
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

/** 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;
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容