溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

ReentrantLock源碼分析--jdk1.8

發(fā)布時間:2020-06-20 10:55:01 來源:網(wǎng)絡(luò) 閱讀:834 作者:jiazhipeng12 欄目:編程語言

JDK1.8

ArrayList源碼分析--jdk1.8
LinkedList源碼分析--jdk1.8
HashMap源碼分析--jdk1.8
AQS源碼分析--jdk1.8
ReentrantLock源碼分析--jdk1.8

ReentrantLock概述

??1. ReentrantLock是獨(dú)占鎖。
??2. ReentrantLock分為公平模式和非公平模式。
??3. ReentrantLock鎖可重入(重新插入)

ReentrantLock源碼分析

/**
 * @since 1.5
 * @author Doug Lea
 * 獨(dú)占鎖 --默認(rèn)使用非公平鎖模式
 * 可重入
 * 
 * synchronized鎖通過監(jiān)視器Monitor來實(shí)現(xiàn)同步,monitorenter加鎖,monitorexit解鎖。
 * synchronized是可重如的非公平鎖
 * synchronized在jdk1.6進(jìn)行優(yōu)化,添加了偏向鎖、輕量級鎖、重量級鎖,關(guān)鍵字之鎖的升級(偏向鎖->輕量級鎖->重量級鎖)
 * 偏向鎖:當(dāng)線程訪問同步塊時,會使用 CAS 將線程 ID 更新到鎖對象的 Mark Word 中,如果更新成功則獲得偏向鎖,并且之后每次進(jìn)入這個對象鎖相關(guān)的同步塊時都不需要再次獲取鎖了。
 * 輕量級鎖:如果同步對象為無鎖狀態(tài)時,直接嘗試CAS更新Mark Word添加鎖,如果成功,獲得鎖,失敗升級為重量級鎖
 * 重量級鎖:是指當(dāng)鎖是輕量級鎖時,當(dāng)自旋的線程自旋了一定的次數(shù)后,還沒有獲取到鎖,就會進(jìn)入阻塞狀態(tài),該鎖升級為重量級鎖,重量級鎖會使其他線程阻塞,性能降低。
 * 在使用 CAS 時,如果操作失敗,CAS 會自旋再次嘗試。由于自旋是需要消耗 CPU 資源的,所以如果長期自旋就白白浪費(fèi)了 CPU。JDK1.6加入了適應(yīng)性自旋:如果某個鎖自旋很少成功獲得,那么下一次就會減少自旋。
 */
public class ReentrantLock implements Lock, java.io.Serializable {

    private static final long serialVersionUID = 7373984872572414699L;

    private final Sync sync;

    /**
     * Sync內(nèi)部類,繼承AQS,實(shí)現(xiàn)獨(dú)占鎖模式,作為基礎(chǔ)內(nèi)部類
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * 加鎖
         */
        abstract void lock();

        /**
         * 判斷 reentranLock 狀態(tài) 是否被鎖?。╯tate ?= 0)
         * <p>如果沒被鎖住嘗試 原子性上鎖 失敗返回false</>
         * <p>如果被鎖住 判斷是否是當(dāng)前線程持有鎖(重入鎖的實(shí)現(xiàn)) 如果是 state + 1
         * (信號量  記錄該線程持有鎖的次數(shù)。 該線程每次釋放所 信號量 -1。 信號量為零 代表 鎖被真正釋放)</>
         * <p>else 返回false</p>
         */
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread(); //獲取到當(dāng)前的線程
            int c = getState(); //獲取鎖的狀態(tài)
            if (c == 0) { //目前沒有人在占有鎖 如果鎖已被經(jīng)釋放 再次嘗試獲取鎖
                if (compareAndSetState(0, acquires)) { //直接嘗試把當(dāng)前只設(shè)置成1,如果成功,把owner設(shè)置自己,并且退出
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) { // 如果當(dāng)前線程為鎖的擁有者
                int nextc = c + acquires; //這里就是重入鎖的概念,如果還是自己,則進(jìn)行加1操作,因?yàn)獒尫藕瞳@取一定要是對等的
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc); // 累加 state 的值  此段代碼 實(shí)現(xiàn)了重入鎖
                return true;
            }
            return false; //當(dāng)前鎖被其他線程占用,退出。
        }

        /**
         * 釋放鎖,默認(rèn)releases傳1
         */
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases; //獲取當(dāng)前的鎖的狀態(tài)并且減1,因?yàn)橐尫沛i
            if (Thread.currentThread() != getExclusiveOwnerThread()) //如果當(dāng)前自己不是鎖的持有者,只有自己才能釋放鎖
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) { //釋放成功
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c); //重新設(shè)置成狀態(tài)
            return free;
        }

        /**
         * 如果當(dāng)前線程獨(dú)占著鎖,返回true
         */
        protected final boolean isHeldExclusively() {
            // While we must in general read state before owner,
            // we don't need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        /**
         * 條件隊(duì)列
         */
        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        /**
         * 返回鎖的擁有者的線程
         * 當(dāng)前狀態(tài)為0返回null,說明在等待中
         * 當(dāng)前狀態(tài)不為0返回當(dāng)前線程
         */
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        /**
         * 當(dāng)前線程占著鎖返回 state,否則返回0
         */
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        /**
         * state狀態(tài)不為0標(biāo)識上鎖,為0表示在等待,不上鎖
         */
        final boolean isLocked() {
            return getState() != 0;
        }

        /**
         * 反序列化
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }
    /**
     * 構(gòu)造方法,默認(rèn)選擇非公平鎖
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * 構(gòu)造方法,true公平鎖,false非公平鎖
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

ReentrantLock繼承和實(shí)現(xiàn)分析

ReentrantLock源碼分析--jdk1.8

?? ReentrantLock implements Lock
?? Sync extends AbstractQueuedSynchronizer
?? 1.ReentrantLock實(shí)現(xiàn)Lock接口,Lock接口定義了加鎖、條件隊(duì)列、解鎖、加鎖(中斷異常)
?? 2.Sync繼承AQS抽象類,實(shí)現(xiàn)了獨(dú)占鎖,作為基礎(chǔ)內(nèi)部類

ReentrantLock源碼分析

1. FairSync公平鎖--內(nèi)部類

/**
 * 公平鎖
 */
static final class FairSync extends Sync {
    private static final long serialVersionUID = -3000897897090466540L;

    final void lock() {
        acquire(1);
    }
    /**
     * Fair version of tryAcquire.  Don't grant access unless
     * recursive call or no waiters or is first.
     */
    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;
    }
}

2. NonfairSync非公平鎖--內(nèi)部類

/**
 * 非公平鎖的同步對象
 */
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = 7316153563782823691L;

    /**
     * Performs lock.  Try immediate barge, backing up to normal
     * acquire on failure.
     * 非公平鎖,每次先去獲取對象,所以不排隊(duì),不公平
     */
    final void lock() {
        //  通過原子操作 改變上鎖狀態(tài)
        if (compareAndSetState(0, 1)) // 變更成功,說明獲取鎖成功
            setExclusiveOwnerThread(Thread.currentThread()); // 設(shè)置持有者為當(dāng)前線程
        else //變更失敗
            acquire(1); //嘗試以獨(dú)占模式獲取鎖,如果失敗加入node節(jié)點(diǎn)到隊(duì)列中
    }
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}
/**
 * 是否有等待線程
 */
public final boolean hasQueuedThreads() {
    return sync.hasQueuedThreads();
}
/**
 * 是否有等待線程
 */
public final boolean hasQueuedThreads() {
    return head != tail;
}

ReentrantLock總結(jié)

1)ReentrantLock是可重入的公平/非公平模式的獨(dú)占鎖。
2)ReentrantLock公平鎖往往沒有非公平鎖的效率高,但是,并不是任何場景都是以TPS作為唯一指標(biāo),公平鎖
能夠減少“饑餓”發(fā)生的概率,等待越久的請求越能夠得到優(yōu)先滿足。
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI