鍍金池/ 問(wèn)答/Java/ 關(guān)于ReentrantLock的lock()方法的一個(gè)疑問(wèn)

關(guān)于ReentrantLock的lock()方法的一個(gè)疑問(wèn)

公平鎖和非公平鎖在嘗試獲取鎖失敗!tryAcquire(arg)后,會(huì)調(diào)用acquireQueued(addWaiter(Node.EXCLUSIVE), arg)方法,方法源碼如下:

圖片描述

為什么這里p==head的時(shí)候才會(huì)再次嘗試獲取鎖?對(duì)于非公平鎖,競(jìng)爭(zhēng)鎖是不依賴(lài)排隊(duì)順序的,不是應(yīng)該不管前驅(qū)結(jié)點(diǎn)是否是head,都應(yīng)該再次去嘗試獲取鎖嗎?

回答
編輯回答
解夏

在同步器中的節(jié)點(diǎn),始終是有順序的。非公平指的是沒(méi)有進(jìn)入同步隊(duì)列的線(xiàn)程與首節(jié)點(diǎn)的后繼節(jié)點(diǎn)中的線(xiàn)程非公平,也有可能是首節(jié)點(diǎn)中的線(xiàn)程和首節(jié)點(diǎn)后繼節(jié)點(diǎn)中的線(xiàn)程非公平競(jìng)爭(zhēng),比如首節(jié)點(diǎn)中的線(xiàn)程釋放鎖后又立即去獲取鎖。
體現(xiàn)在ReentrantLock代碼中話(huà),就是NonfairSynctryAcquire實(shí)現(xiàn)和FairSynctryAcquire實(shí)現(xiàn)是不一樣的。

static final class NonfairSync extends Sync {
        。。。。。。
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
        。。。。
}
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;
}
static final class FairSync extends Sync {
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
}
public final boolean hasQueuedPredecessors() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
}

FairSynctryAcquire方法,多了一個(gè)!hasQueuedPredecessors()判斷。如果同步隊(duì)列為空,或者只有首節(jié)點(diǎn),或者首節(jié)點(diǎn)的后繼節(jié)點(diǎn)中的線(xiàn)程是當(dāng)前線(xiàn)程,那么hasQueuedPredecessors()false,!hasQueuedPredecessors()為true,調(diào)用tryAcquire的當(dāng)前線(xiàn)程就可以去獲取同步狀態(tài)。

2018年9月20日 16:27