第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

讀寫鎖 StampedLock

1. 前言

本節(jié)帶領(lǐng)大家認識第二個常用的 Java 并發(fā)鎖工具之 StampedLock。

本節(jié)先簡單介紹 StampedLock 的基本概念,然后介紹關(guān)鍵的編程方法,最后通過一個編程例子為大家展示 StampedLock 工具類的用法。

下面我們正式開始介紹吧。

2. 概念解釋

我們先解釋一組概念:悲觀鎖、樂觀鎖。

悲觀鎖 指的是對數(shù)據(jù)修改持保守態(tài)度,在整個數(shù)據(jù)處理時,先將數(shù)據(jù)鎖定狀態(tài),然后再進行修改處理。之所以叫做悲觀鎖,是因為這是一種對數(shù)據(jù)的修改抱有悲觀態(tài)度的并發(fā)控制方式,認為數(shù)據(jù)被并發(fā)修改的概率比較大,所以需要在修改之前先加鎖。

樂觀鎖 正好相反,抱著數(shù)據(jù)訪問一般情況下不會造成沖突的觀點,先對數(shù)據(jù)做修改,在正式提交修改結(jié)果是才會做沖突檢查,如果發(fā)現(xiàn)修改的是舊版本的數(shù)據(jù),則返回修改失敗,否則提交修改。

StampedLock 是對 ReentrantReadWriteLock 的改進。相比 ReentrantReadWriteLock 采用了悲觀鎖的思想對數(shù)據(jù)修改的并發(fā)控制,StampedLock 使用了樂觀思想的加鎖實現(xiàn),具有更高的并發(fā)性。

下面我們學習其關(guān)鍵的編程方法。

3. StampedLock 的編程方法

StampedLock 提供了三種并發(fā)控制模式,介紹這三種模式過程中,我們穿插介紹關(guān)鍵的編程方法。

3.1. 獨占寫模式

功能和 ReentrantReadWriteLock 的寫鎖類似。獨占寫模式相關(guān)的幾個方法如下。

long stamp = writeLock () 方法:獲取獨占寫鎖,可能會被阻塞。如果獲取鎖成功則返回一個 stamp;
tryWriteLock () 方法:嘗試獲取獨占寫鎖,類似 writeLock () 方法,只是獲取不到時立刻返回不會阻塞;
tryWriteLock (long time, TimeUnit unit) 方法:允許在給定的時間內(nèi)嘗試獲取獨占寫鎖,超時仍然未獲取到時則返回;
writeLockInterruptibly () 方法:類似 writeLock () 但允許獲取鎖的過程被打斷;
unlockWrite (long stamp) 方法:用于釋放獨占寫鎖;
tryUnlockWrite () 方法:類似 unlockWrite (), 但允許不需要 stamp 郵戳參數(shù)。

3.2. 悲觀讀模式

功能和 ReentrantReadWriteLock 的讀鎖類似。悲觀讀模式相關(guān)的幾個方法如下。

long stamp = readLock () 方法:獲取獨占讀鎖,可能會被阻塞。如果獲取鎖成功則返回一個 stamp;
unlockRead (long stamp) 方法:用于釋放讀鎖;
tryReadLock () 方法:嘗試獲取讀鎖,類似 readLock () 方法,只是獲取不到時立刻返回不會阻塞;
tryReadLock (long time, TimeUnit unit) 方法:允許在給定的時間內(nèi)嘗試獲取讀鎖,超時仍然未獲取到時則返回;
readLockInterruptibly () 方法:類似 readLock () 但允許獲取鎖的過程被打斷。

3.3. 樂觀讀模式

這是一種優(yōu)化的讀模式。樂觀讀模式相關(guān)的幾個方法如下。

tryOptimisticRead () 方法:非阻塞嘗試樂觀獲取讀鎖,只有當寫鎖沒有被獲取時返回一個非 0 的 stamp 。樂觀讀取模式適用于短時間讀取操作,降低競爭和提高吞吐量。在使用時一般需將數(shù)據(jù)存儲到一個副本中,在后繼處理中用于對比數(shù)據(jù)是否是最新狀態(tài);
validate (long stamp) 方法:用于檢查在獲取到讀鎖 stamp 后,鎖有沒被其他寫線程搶占。如果寫鎖沒有被獲取,那么 validate () 方法返回 true??啥啻握{(diào)用驗證這一信息。

另外,此類也提供了一組讀寫鎖之間的轉(zhuǎn)換方法

tryConvertToWriteLock (long stamp) 方法:嘗試轉(zhuǎn)換為寫鎖。轉(zhuǎn)換條件:
tryConvertToReadLock (long stamp) 方法:嘗試轉(zhuǎn)換為悲觀讀鎖。
tryConvertToOptimisticRead (long stamp) 方法:嘗試轉(zhuǎn)換為樂觀讀鎖。

注意此類的編程方法有這樣一個共通特征:
所有獲取鎖的方法,都返回一個郵戳(Stamp),Stamp 為 0 表示獲取失敗,其余都表示成功;
所有釋放鎖的方法,都需要一個郵戳(Stamp),這個 Stamp 必須是和成功獲取鎖時得到的 Stamp 一致;

下面我們舉一個具體的編程例子。

4. 編程示例

上面介紹了核心編程方法,我們給出一個非常簡潔明了的官方例子,切實體會一下 StampedLock 的用法。

import java.util.concurrent.locks.StampedLock;

public class StampedLockTest {

    // 成員變量
    private double x, y;

    // 鎖實例
    private final StampedLock sl = new StampedLock();

    // 排它鎖-寫鎖(writeLock)
    void move(double deltaX, double deltaY) {
        long stamp = sl.writeLock();
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            sl.unlockWrite(stamp);
        }
    }

    // 一個只讀方法
    // 其中存在樂觀讀鎖到悲觀讀鎖的轉(zhuǎn)換
    double distanceFromOrigin() {

        // 嘗試獲取樂觀讀鎖
        long stamp = sl.tryOptimisticRead();
        // 將全部變量拷貝到方法體棧內(nèi)
        double currentX = x, currentY = y;
        // 檢查在獲取到讀鎖stamp后,鎖有沒被其他寫線程搶占
        if (!sl.validate(stamp)) {
            // 如果被搶占則獲取一個共享讀鎖(悲觀獲?。?/span>
            stamp = sl.readLock();
            try {
                // 將全部變量拷貝到方法體棧內(nèi)
                currentX = x;
                currentY = y;
            } finally {
                // 釋放共享讀鎖
                sl.unlockRead(stamp);
            }
        }
        // 返回計算結(jié)果
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }

    // 獲取讀鎖,并嘗試轉(zhuǎn)換為寫鎖
    void moveIfAtOrigin(double newX, double newY) {
        long stamp = sl.tryOptimisticRead();
        try {
            // 如果當前點在原點則移動
            while (x == 0.0 && y == 0.0) {
                // 嘗試將獲取的讀鎖升級為寫鎖
                long ws = sl.tryConvertToWriteLock(stamp);
                // 升級成功,則更新stamp,并設置坐標值,然后退出循環(huán)
                if (ws != 0L) {
                    stamp = ws;
                    x = newX;
                    y = newY;
                    break;
                } else {
                    // 讀鎖升級寫鎖失敗則釋放讀鎖,顯示獲取獨占寫鎖,然后循環(huán)重試
                    sl.unlockRead(stamp);
                    stamp = sl.writeLock();
                }
            }
        } finally {
            sl.unlock(stamp);
        }
    }
}

注意在使用時,獲取鎖的操作應該放在 try 之前,而釋放鎖的操作需要放在 finally 中,可確保鎖釋放。另外需要注意 StampedLock 具有不可重入性。

5. 小結(jié)

本節(jié)解釋了 StampedLock 的基本概念和主要的編程方法,且通過一個簡單的例子展示了其用法,更多關(guān)于此工具類的概念和原理介紹,可閱讀 “Java 并發(fā)原理入門教程” 。希望大家在學習過程中,多思考勤練習,早日掌握之。