国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

J.U.C|讀-寫鎖ReentrantReadWriteLock

Tonny / 2253人閱讀

摘要:所以就有了讀寫鎖。只要沒有,讀取鎖可以由多個線程同時保持。其讀寫鎖為兩個內(nèi)部類都實現(xiàn)了接口。讀寫鎖同樣依賴自定義同步器來實現(xiàn)同步狀態(tài)的,而讀寫狀態(tài)就是其自定義同步器的狀態(tài)。判斷申請寫鎖數(shù)量是否超標(biāo)超標(biāo)則直接異常,反之則設(shè)置共享狀態(tài)。

一、寫在前面

在上篇我們聊到了可重入鎖(排它鎖)ReentrantLcok ,具體參見《J.U.C|可重入鎖ReentrantLock》

ReentrantLcok 屬于排它鎖,本章我們再來一起聊聊另一個我們工作中出鏡率很高的讀-寫鎖。

二、簡介

重入鎖ReentrantLock是排他鎖(互斥鎖),排他鎖在同一時刻僅有一個線程可訪問,但是在大多數(shù)場景下,大部分時間都是提供讀服務(wù)的,而寫服務(wù)占用極少的時間,然而讀服務(wù)不存在數(shù)據(jù)競爭的問題,如果一個線程在讀時禁止其他線程讀勢必會降低性能。所以就有了讀寫鎖。

讀寫鎖內(nèi)部維護(hù)著一對鎖,一個讀鎖和一個寫鎖。通過分離讀鎖和寫鎖,使得并發(fā)性比一般排他鎖有著顯著的提升。

讀寫鎖在同一時間可以允許多個讀線程同時訪問,但是寫線程訪問時,所有的讀線程和寫線程都會阻塞。

主要有以下特征:

公平性選擇:支持非公平(默認(rèn))和公平的鎖獲取方式,吞吐量還是非公平優(yōu)于公平。

重進(jìn)入:該鎖支持重進(jìn)入,以讀寫線程為列,讀線程在獲取到讀鎖之后,能再次獲取讀鎖。而寫線程在獲取寫鎖后能夠再次獲取寫鎖,同時也可以獲取讀鎖。

鎖降級:遵循獲取寫鎖、讀鎖再釋放寫鎖的次序,寫鎖能夠降級成為讀鎖。

讀寫鎖最多支持65535個遞歸寫入鎖和65535個遞歸讀取鎖。 鎖降級:遵循獲取寫鎖、獲取讀鎖在釋放寫鎖的次序,寫鎖能夠降級成為讀鎖 讀寫鎖ReentrantReadWriteLock實現(xiàn)接口ReadWriteLock,該接口維護(hù)了一對相關(guān)的鎖,一個用于只讀操作,另一個用于寫入操作。只要沒有 writer,讀取鎖可以由多個 reader 線程同時保持。

三、主要方法介紹

讀寫鎖ReentrantReadWriteLock 實現(xiàn)了ReadWriteLock 接口,該接口維護(hù)一對相關(guān)的鎖即讀鎖和寫鎖。

public interface ReadWriteLock {
    /**
     * Returns the lock used for reading.
     *
     * @return the lock used for reading
     */
    Lock readLock();

    /**
     * Returns the lock used for writing.
     *
     * @return the lock used for writing
     */
    Lock writeLock();
}

ReadWriteLock定義了兩個方法。readLock()返回用于讀操作的鎖,writeLock()返回用于寫操作的鎖。ReentrantReadWriteLock定義如下:

/** 內(nèi)部類 讀鎖*/
private final ReentrantReadWriteLock.ReadLock readerLock;
 /** 內(nèi)部類 寫鎖*/
private final ReentrantReadWriteLock.WriteLock writerLock;
/** 執(zhí)行所有同步機(jī)制 */
final Sync sync;

// 默認(rèn)實現(xiàn)非公平鎖
public ReentrantReadWriteLock() {
    this(false);
}
// 利用給定的公平策略初始化ReentrantReadWriteLock
public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
 }
 
 // 返回寫鎖
 public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
 //返回讀鎖
 public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
 
 // 實現(xiàn)同步器,也是實現(xiàn)鎖的核心
 abstract static class Sync extends AbstractQueuedSynchronizer {
    // 省略實現(xiàn)代碼
 }
 
 // 公平鎖的實現(xiàn)
 static final class FairSync extends Sync {
    // 省略實現(xiàn)代碼
 }
 // 非公平鎖的實現(xiàn)
 static final class NonfairSync extends Sync {
    // 省略實現(xiàn)代碼
 }
 
 // 讀鎖實現(xiàn)
 public static class ReadLock implements Lock, java.io.Serializable {
    // 省略實現(xiàn)代碼
 }
 // 寫鎖實現(xiàn)
 public static class WriteLock implements Lock, java.io.Serializable {
    // 省略實現(xiàn)代碼
 }

ReentrantReadWriteLock 和 ReentrantLock 其實都一樣,鎖核心都是Sync, 讀鎖和寫鎖都是基于Sync來實現(xiàn)的。從這分析其實ReentrantReadWriteLock就是一個鎖,只不過內(nèi)部根據(jù)不同的場景設(shè)計了兩個不同的實現(xiàn)方式。其讀寫鎖為兩個內(nèi)部類: ReadLock、WriteLock 都實現(xiàn)了Lock 接口。

讀寫鎖同樣依賴自定義同步器來實現(xiàn)同步狀態(tài)的, 而讀寫狀態(tài)就是其自定義同步器的狀態(tài)?;叵隦eentantLock 中自定義同步器的實現(xiàn),同步狀態(tài)表示鎖被一個線程重復(fù)獲取的次數(shù),而讀寫鎖中的自定義同步器需要在一個同步狀態(tài)(一個整型變量)上維護(hù)多個讀線程和寫線程的狀況,而該狀態(tài)的設(shè)計成為關(guān)鍵。

如何在一個整型上維護(hù)多種狀態(tài),那就需要‘按位切割使用’這個變量,讀寫鎖將變量切割成兩部分,高16位表示讀,低16位表示寫。

分割之后,讀寫鎖是如何迅速確定讀鎖和寫鎖的狀態(tài)呢?通過位運(yùn)算,假如當(dāng)前同步狀態(tài)為S,那么寫狀態(tài)等于 S & 0x0000FFFF(將高16位全部抹去),讀狀態(tài)等于S >>> 16(無符號補(bǔ)0右移16位)。代碼如下:

static final int SHARED_SHIFT   = 16;
static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

/** Returns the number of shared holds represented in count  */
static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
/** Returns the number of exclusive holds represented in count  */
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
四、寫鎖的獲取與釋放

寫鎖是一個支持重入的排他鎖,如果當(dāng)前線程已經(jīng)獲取了寫鎖,則增加寫狀態(tài)。如果當(dāng)前線程獲取寫鎖時讀鎖已經(jīng)被獲取或者該線程不是已經(jīng)獲取寫鎖的線程,則當(dāng)前線程進(jìn)入等待狀態(tài)。

寫鎖的獲取

寫鎖的獲取入口通過WriteLock的lock方法

public void lock() {
   sync.acquire(1);
}

Sync的acquire(1)方法 定義在AQS中

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
}

tryAcquire(arg) 方法除了重入方法外,還增加了是否存在讀鎖的判斷,如果讀鎖存在、則不能獲取寫鎖。原因在于寫操作要對所有的讀操作的可見性。

protected final boolean tryAcquire(int acquires) {
            Thread current = Thread.currentThread();
            // 獲取同步狀態(tài)
            int c = getState();
            // 獲取寫鎖的獲取次數(shù)
            int w = exclusiveCount(c);
             // 已有線程獲取鎖
            if (c != 0) {
                // (Note: if c != 0 and w == 0 then shared count != 0)
                /**
                 * w == 0 表示存在讀鎖(同步狀態(tài)不等于0說明已有線程獲取到鎖(讀/寫)
                 * 而寫鎖狀態(tài)為0則說明不存在寫鎖,所以只能是讀鎖了)
                 * current != getExclusiveOwnerThread()) 不是自己獲取的寫鎖
                 * 
                 * 如果存在讀鎖或者持有寫鎖的線程不是自己,直接返回false
                 */
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                    
                 // 如果獲取寫鎖的數(shù)量超過最大值65535 ,直接異常
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // Reentrant acquire
                // 設(shè)置共享狀態(tài)
                setState(c + acquires);
                return true;
            }
             
             /**
             * writerShouldBlock() 是否需要阻塞寫鎖,這里直接返回的是false
             * compareAndSetState(c, c + acquires) 設(shè)置寫鎖的狀態(tài)
             */
            
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;   
    }
小結(jié)

寫鎖的獲取基本和RenntrantLock 類似
判斷當(dāng)前是否有線程持有寫鎖(寫鎖的狀態(tài)是否為0)
寫鎖的狀態(tài)不為0,如果存在讀鎖或者寫鎖不是自己持有則直接返回fasle。
判斷申請寫鎖數(shù)量是否超標(biāo)(> 65535),超標(biāo)則直接異常,反之則設(shè)置共享狀態(tài)。
寫鎖狀態(tài)為0,如果寫鎖需要阻塞或者CAS設(shè)置共享狀態(tài)失敗,則直接返回false,否則獲取鎖成功,設(shè)置持鎖線程為自己。

來張圖加深下理解

寫鎖的釋放

寫鎖的釋放和ReentrantLock 極為相似, 每次釋放就是狀態(tài)減1 ,當(dāng)狀態(tài)為0表示釋放成功。

寫鎖釋放的入口WriteLock中的unlock方法

public void unlock() {
      sync.release(1)
 }

Sync 中release方法由AQS中實現(xiàn)的

public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

tryRelease(arg) 方法釋放共享狀態(tài),非常簡單就是共享狀態(tài)減1,為0表示釋放成功

protected final boolean tryRelease(int releases) {
            // 判斷鎖持有者是否是自己
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
             // 共享狀態(tài)值 - release
            int nextc = getState() - releases;
            // 判斷寫鎖數(shù)量是否為0
            boolean free = exclusiveCount(nextc) == 0;
            if (free)
                setExclusiveOwnerThread(null);
            setState(nextc);
            return free;
        }
小結(jié)

寫鎖的釋放很簡單

首先判斷鎖持有者不是自己則直接異常

是自己則將共享狀態(tài) -1

判斷寫鎖數(shù)量是否為0,如果為0將持有鎖線程變量設(shè)為null

設(shè)置共享狀態(tài)

來張圖加深下理解

五、讀鎖的獲取與釋放

讀鎖為一個可重入的共享鎖,它能夠被多個線程同時持有,在沒有其他寫線程訪問時,讀鎖總是獲取成功,所需要的也就是(線程安全的)增加讀狀態(tài)。

讀鎖的獲取

讀鎖的獲取可以通過ReadLock.lock()方法。

public void lock() {
    //讀鎖是一個可重入共享鎖,委托給內(nèi)部類Sync實現(xiàn)
     sync.acquireShared(1);
}

Sync的acquireShared(1)方法定義在AQS中

public final void acquireShared(int arg) {
        // AQS 中 嘗試獲取共享狀態(tài),如果共享狀態(tài)大于等于0則說明獲取鎖成功,否則加入同步隊列。
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }

tryAcquireShared(int unused)方法中,如果其他線程獲取了寫鎖,則讀鎖獲取失敗線程將進(jìn)入等待狀態(tài),如果當(dāng)前線程獲取寫鎖或者寫鎖未被獲取則利用CAS(線程安全的)增加同步狀態(tài),成功則獲取鎖。

protected final int tryAcquireShared(int unused) {
            
            Thread current = Thread.currentThread();
            // 獲取共享狀態(tài)
            int c = getState();
            // 判斷是否有寫鎖 && 持有寫鎖的線程是否是自己,為true直接返回-1 
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
             //獲取共享資源的數(shù)量
            int r = sharedCount(c);
           
           /**
              * readerShouldBlock():判斷鎖是否需要等待(公平鎖原則)
              * r < MAX_COUNT:判斷鎖的數(shù)量是否超過最大值65535
              * compareAndSetState(c, c + SHARED_UNIT): 設(shè)置共享狀態(tài)(讀鎖狀態(tài))
              */
              
            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                // r==0 :當(dāng)前沒有任何線程獲取讀鎖
                if (r == 0) {
                    // 設(shè)置當(dāng)前線程為第一個獲取讀鎖的線程
                    firstReader = current;
                    // 計數(shù)設(shè)置為1
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    // 表示重入鎖,在計數(shù)其上+1
                    firstReaderHoldCount++;
                } else {
                    
                    /**
                     *  HoldCounter 主要是一個類來記錄線程獲取鎖的數(shù)量
                     *  cachedHoldCounter 緩存的是最后一個獲取鎖線程的HoldCounter對象
                     */
                     
                    HoldCounter rh = cachedHoldCounter;
                    // 如果緩存不存在,或者線程不是自己
                    if (rh == null || rh.tid != getThreadId(current))
                        // 從當(dāng)前線程本地變量ThreadLocalHoldCounter 中獲取HoldCounter 并賦值給 cachedHoldCounter, rh
                        cachedHoldCounter = rh = readHolds.get();
                     // 如果緩存的HoldCounter 是當(dāng)前的線程的,且計數(shù)為0 
                    else if (rh.count == 0)
                        // 將rh 存到ThreadLocalHoldCounter 中,將計數(shù)+1 
                        readHolds.set(rh);
                    rh.count++;
                }
                return 1;
            }
            /**
             * 進(jìn)入fullTryAcquireShared(current) 條件
             * 1: readerShouldBlock()  = true  
             * 2: r < MAX_COUNT = false  讀鎖達(dá)到最大
             * 3: 設(shè)置共享狀態(tài)失敗
            return fullTryAcquireShared(current);
        }

NonfairSync 中的 readerShouldBlock() 方法判斷當(dāng)前申請讀鎖的線程是否需要阻塞

final boolean readerShouldBlock() {
            return apparentlyFirstQueuedIsExclusive();
        }

apparentlyFirstQueuedIsExclusive() 判斷同步隊列中老二節(jié)點(diǎn)是否是獨(dú)占式(獲取寫鎖請求)是返回ture 否則返回false

final boolean apparentlyFirstQueuedIsExclusive() {
        Node h, s;
        // 主要條件判斷下一個節(jié)點(diǎn)是否是獲取寫鎖線程在排隊
        return (h = head) != null &&
            (s = h.next)  != null &&
            !s.isShared()         &&
            s.thread != null;
    }

自旋來獲取讀鎖,個人感覺對tryAcquireShared(int unused) 方法獲取讀鎖失敗的一種補(bǔ)救,其實現(xiàn)邏輯基本相同。

final int fullTryAcquireShared(Thread current) {
            // 線程內(nèi)部計數(shù)器
            HoldCounter rh = null;
            // 自旋
            for (;;) {
                // 獲取共享狀態(tài)
                int c = getState();
               
               /**
                 * exclusiveCount(c) !=0:存在獨(dú)占鎖(寫鎖)
                 * getExclusiveOwnerThread() != current 判斷是否是自己持有寫鎖
                 * 再次是寫鎖是否是自己
                 */
                 
                if (exclusiveCount(c) != 0) {
                    if (getExclusiveOwnerThread() != current)
                        return -1;
                   
                } else if (readerShouldBlock()) {//判斷讀鎖是否需要阻塞
                    // 如果需要阻塞,表示除了當(dāng)前線程持有寫鎖外,還有其他線程在等待獲取寫鎖,故,即使申請讀鎖的線程已經(jīng)持有寫鎖(寫鎖內(nèi)部再次申請讀鎖,俗稱鎖降級)還是會失敗,因為有其他線程也在申請寫鎖,此時,只能結(jié)束本次申請讀鎖的請求,轉(zhuǎn)而去排隊,否則,將造成死鎖
                    if (firstReader == current) {
                        // assert firstReaderHoldCount > 0;
                    } else {
                        // 到這里其實就寫鎖的一個讓步, 清楚HoldCounter 緩存
                        if (rh == null) {
                            rh = cachedHoldCounter;
                            if (rh == null || rh.tid != getThreadId(current)) {
                                rh = readHolds.get();
                                if (rh.count == 0)
                                    readHolds.remove();
                            }
                        }
                        if (rh.count == 0)
                            return -1;
                    }
                }
                // 下面邏輯和tryAcquireShared(int unused) 基本相同不再解釋了
                if (sharedCount(c) == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                if (compareAndSetState(c, c + SHARED_UNIT)) {
                    if (sharedCount(c) == 0) {
                        firstReader = current;
                        firstReaderHoldCount = 1;
                    } else if (firstReader == current) {
                        firstReaderHoldCount++;
                    } else {
                        if (rh == null)
                            rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current))
                            rh = readHolds.get();
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        rh.count++;
                        cachedHoldCounter = rh; // cache for release
                    }
                    return 1;
                }
            }
        }
小結(jié)

讀鎖的獲取稍微有點(diǎn)復(fù)雜,整個過程如下

如果其他線程獲取了寫鎖、則獲取讀鎖失敗。

如果當(dāng)前線程獲取到了寫鎖或者寫鎖未被獲取則利用CAS(線程安全的)增加讀鎖狀態(tài)

否則 fullTryAcquireShared(Thread current) 自旋方式再次來嘗試獲取。

讀鎖獲取流程圖如下

讀鎖的釋放

讀鎖的釋放通過ReadLock的unlock()方式釋放的。

public void unlock() {
            sync.releaseShared(1);
        }

Sync的releaseShared(1)同樣定義在AQS中

public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

調(diào)用tryReleaseShared(int unused) 方法來釋放共享狀態(tài)。

protected final boolean tryReleaseShared(int unused) {
            Thread current = Thread.currentThread();
            //判斷當(dāng)前線程釋放是第一個獲取讀鎖的線程
            if (firstReader == current) {
                // assert firstReaderHoldCount > 0;
                // 判斷獲取鎖的次數(shù)釋放為1,如果為1說明沒有重入情況,直接釋放firstReader = null;否則將該線程持有鎖的數(shù)量 -1
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                else
                    firstReaderHoldCount--;
            } else {
                // 如果當(dāng)前線程不是第一個獲取讀鎖的線程。
                
                // 獲取緩存中的HoldCounter
                HoldCounter rh = cachedHoldCounter;
                // 如果緩存中的HoldCounter 不屬于當(dāng)前線程則獲取當(dāng)前線程的HoldCounter。
                if (rh == null || rh.tid != getThreadId(current))
                    rh = readHolds.get();
                int count = rh.count;
                if (count <= 1) {
                    // 如果線程持有鎖的數(shù)量小于等1 直接刪除HoldCounter
                    readHolds.remove();
                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                // 持有鎖數(shù)量大于1 則執(zhí)行 - 1操作
                --rh.count;
            }
            // 自旋釋放同步狀態(tài)
            for (;;) {
                int c = getState();
                int nextc = c - SHARED_UNIT;
                if (compareAndSetState(c, nextc))
                    // Releasing the read lock has no effect on readers,
                    // but it may allow waiting writers to proceed if
                    // both read and write locks are now free.
                    return nextc == 0;
            }
        }
小結(jié)

鎖的釋放比較簡單,

首先看當(dāng)前線程是否是第一個獲取讀鎖的線程,如果是并且沒有發(fā)生重入,則將首次獲取讀鎖變量設(shè)為null, 如果發(fā)生重入,則將首次獲取讀鎖計數(shù)器 -1

其次 查看緩存中計數(shù)器是否為空或者是否是當(dāng)前線程,如果為空或者不是則獲取當(dāng)前線程的計數(shù)器,如果計數(shù)器個數(shù)小于等1, 從ThreadLocl 中刪除計數(shù)器,并計數(shù)器值-1,如果小于等于0異常 。

最后自旋修改同步狀態(tài)。

讀鎖釋放流程圖如下

六、總結(jié)

通過上面的源碼分析,我們來總結(jié)下:

在線程持有讀鎖的情況下,該線程不能取得寫鎖(為了保證寫操作對后續(xù)所有的讀操作保持可見性)。

在線程持有寫鎖的情況下,該線程可以繼續(xù)獲取讀鎖(獲取讀鎖時如果發(fā)現(xiàn)寫鎖被占用,只有寫鎖沒有被當(dāng)前線程占用的情況才會獲取失?。?。

仔細(xì)想想,這個設(shè)計是合理的:因為當(dāng)線程獲取讀鎖的時候,可能有其他線程同時也在持有讀鎖,因此不能把獲取讀鎖的線程“升級”為寫鎖;而對于獲得寫鎖的線程,它一定獨(dú)占了讀寫鎖,因此可以繼續(xù)讓它獲取讀鎖,當(dāng)它同時獲取了寫鎖和讀鎖后,還可以先釋放寫鎖繼續(xù)持有讀鎖,這樣一個寫鎖就“降級”為了讀

一個線程要想同時持有寫鎖和讀鎖,必須先獲取寫鎖再獲取讀鎖;寫鎖可以“降級”為讀鎖;讀鎖不能“升級”為寫鎖。

因技術(shù)水平有限,如有不對的地方,歡迎拍磚

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/77621.html

相關(guān)文章

  • J.U.C|-寫鎖ReentrantReadWriteLock

    摘要:所以就有了讀寫鎖。只要沒有,讀取鎖可以由多個線程同時保持。其讀寫鎖為兩個內(nèi)部類都實現(xiàn)了接口。讀寫鎖同樣依賴自定義同步器來實現(xiàn)同步狀態(tài)的,而讀寫狀態(tài)就是其自定義同步器的狀態(tài)。判斷申請寫鎖數(shù)量是否超標(biāo)超標(biāo)則直接異常,反之則設(shè)置共享狀態(tài)。 一、寫在前面 在上篇我們聊到了可重入鎖(排它鎖)ReentrantLcok ,具體參見《J.U.C|可重入鎖ReentrantLock》 Reentra...

    wendux 評論0 收藏0
  • Java多線程進(jìn)階(十)—— J.U.C之locks框架:基于AQS的寫鎖(5)

    摘要:關(guān)于,最后有兩點(diǎn)規(guī)律需要注意當(dāng)?shù)牡却犃嘘犑捉Y(jié)點(diǎn)是共享結(jié)點(diǎn),說明當(dāng)前寫鎖被占用,當(dāng)寫鎖釋放時,會以傳播的方式喚醒頭結(jié)點(diǎn)之后緊鄰的各個共享結(jié)點(diǎn)。當(dāng)?shù)牡却犃嘘犑捉Y(jié)點(diǎn)是獨(dú)占結(jié)點(diǎn),說明當(dāng)前讀鎖被使用,當(dāng)讀鎖釋放歸零后,會喚醒隊首的獨(dú)占結(jié)點(diǎn)。 showImg(https://segmentfault.com/img/remote/1460000016012293); 本文首發(fā)于一世流云的專欄:...

    dunizb 評論0 收藏0
  • Java多線程—ReentrantReadWriteLock源碼閱

    摘要:不同的是它還多了內(nèi)部類和內(nèi)部類,以及讀寫對應(yīng)的成員變量和方法。另外是給和內(nèi)部類使用的。內(nèi)部類前面說到的操作是分配到里面執(zhí)行的。他們都是接口的實現(xiàn),所以其實最像應(yīng)該是這個兩個內(nèi)部類。而且大體上也沒什么差異,也是用的內(nèi)部類。 之前講了《AQS源碼閱讀》和《ReentrantLock源碼閱讀》,本次將延續(xù)閱讀下ReentrantReadWriteLock,建議沒看過之前兩篇文章的,先大概了解...

    Ververica 評論0 收藏0
  • ReentrantReadWriteLock 類

    摘要:類顧名思義是一種讀寫鎖它是接口的直接實現(xiàn)該類在內(nèi)部實現(xiàn)了具體獨(dú)占鎖特點(diǎn)的寫鎖以及具有共享鎖特點(diǎn)的讀鎖和一樣類也是通過定義內(nèi)部類實現(xiàn)框架的來實現(xiàn)獨(dú)占共享的功能屬于排他鎖這些鎖在同一時刻只允許一個線程進(jìn)行訪問但是在大多數(shù)場景下大部分時間都是提供 ReentrantReadWriteLock 類, 顧名思義, 是一種讀寫鎖, 它是 ReadWriteLock 接口的直接實現(xiàn), 該類在內(nèi)部實現(xiàn)...

    zsirfs 評論0 收藏0
  • Java多線程進(jìn)階(四)—— J.U.C之locks框架:ReentrantReadWriteLoc

    摘要:我們知道,的作用其實是對類的和的增強(qiáng),是為了讓線程在指定對象上等待,是一種線程之間進(jìn)行協(xié)調(diào)的工具。當(dāng)線程調(diào)用對象的方法時,必須拿到和這個對象關(guān)聯(lián)的鎖。 showImg(https://segmentfault.com/img/remote/1460000016012566); 本文首發(fā)于一世流云的專欄:https://segmentfault.com/blog... 一、Reentr...

    kumfo 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<