Java并發(fā)-重入鎖ReentrantLock

基礎(chǔ)

  • 重入鎖:一個(gè)線(xiàn)程對(duì)同一個(gè)鎖資源可以重復(fù)獲?。ㄈ鐂ynchronized關(guān)鍵字)
  • ReentrantLock是可重入鎖,并且支持獲取鎖時(shí)的公平與非公平選擇。
  • ReentrantLock默認(rèn)為非公平鎖,這是出于性能考慮(對(duì)于非公平鎖,一個(gè)剛釋放鎖的線(xiàn)程很大概率可以再次獲得該鎖,而不用去排隊(duì),減少上下文切換次數(shù))。而公平鎖總是會(huì)讓你到同步隊(duì)列走一遭,即使你剛釋放了鎖,然后立馬請(qǐng)求鎖。即公平鎖的實(shí)現(xiàn)是以線(xiàn)程切換為代價(jià)的。

基本使用

ReentrantLock lock = new ReentrantLock();//非公平鎖
//ReentrantLock lock = new ReentrantLock(true);//公平鎖
        lock.lock();
        try{
            //to do
        }finally {
            lock.unlock();
        }

ReentrantLock的基本骨架

ReentrantLock implements Lock{
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {......};
static final class NonfairSync extends Sync {};//非公平鎖用這個(gè)同步器
static final class FairSync extends Sync {};//公平鎖用這個(gè)同步器
}
public ReentrantLock(boolean fair) {//選擇是公平鎖還是非公平鎖
     sync = fair ? new FairSync() : new NonfairSync();
}
public ReentrantLock() {//默認(rèn)為非公平鎖
        sync = new NonfairSync();
}

源碼角度分析其可重入性和公平性的實(shí)現(xiàn)

可重入特性實(shí)現(xiàn)(非公平鎖為例)

鎖的獲取

如果當(dāng)前同步狀態(tài)已經(jīng)被線(xiàn)程獲?。╯tate != 0),判斷當(dāng)前嘗試獲取同步狀態(tài)的線(xiàn)程是否是已經(jīng)獲取同步狀態(tài)的線(xiàn)程,如果是就代表當(dāng)前線(xiàn)程重入獲取鎖,將同步狀態(tài)的值增加(所以獲取鎖多少次,就應(yīng)該釋放鎖多少次),返回成功。

 final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //可重入特性提現(xiàn)在這里
            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;
        }
鎖的釋放

因?yàn)橥綘顟B(tài)的獲取可能獲取了n次,所以應(yīng)該只有最后一次釋放之后才應(yīng)該返回true(線(xiàn)程已釋放鎖)。

protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

公平性實(shí)現(xiàn)

用戶(hù)層面而言:鎖的獲取嚴(yán)格遵守FIFO模式
源碼角度來(lái)說(shuō):公平鎖的tryAcquire與非公平鎖不同之處在于---公平鎖如果判斷鎖空閑,還需要去判斷同步隊(duì)列中有沒(méi)有在排隊(duì)的(非公平鎖沒(méi)有這一步),如果有的話(huà)就去同步隊(duì)列中排隊(duì)。

protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //公平鎖實(shí)現(xiàn)的關(guān)鍵
                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;
        }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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