Java8 讀寫鎖的改進:StampedLock(筆記)

     StampedLock是Java8引入的一種新的所機制,簡單的理解,能夠認爲它是讀寫鎖的一個改進版本,讀寫鎖雖然分離了讀和寫的功能,使得讀與讀之間能夠徹底併發,可是讀和寫之間依然是衝突的,讀鎖會徹底阻塞寫鎖,它使用的依然是悲觀的鎖策略.若是有大量的讀線程,他也有可能引發寫線程的飢餓
     而StampedLock則提供了一種樂觀的讀策略,這種樂觀策略的鎖很是相似於無鎖的操做,使得樂觀鎖徹底不會阻塞寫線程
  • StampedLock的使用實例
 
 
public class Point {
    private double x, y;//內部定義表示座標點
    private final StampedLock s1 = new StampedLock();//定義了StampedLock鎖,

    void move(double deltaX, double deltaY) {
        long stamp = s1.writeLock();//這裏的含義和distanceFormOrigin方法中 s1.readLock()是相似的
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            s1.unlockWrite(stamp);//退出臨界區,釋放寫鎖
        }
    }

    double distanceFormOrigin() {//只讀方法
        long stamp = s1.tryOptimisticRead();  //試圖嘗試一次樂觀讀 返回一個相似於時間戳的郵戳整數stamp 這個stamp就能夠做爲這一個所獲取的憑證
        double currentX = x, currentY = y;//讀取x和y的值,這時候咱們並不肯定x和y是不是一致的
        if (!s1.validate(stamp)) {//判斷這個stamp是否在讀過程發生期間被修改過,若是stamp沒有被修改過,責任無此次讀取時有效的,所以就能夠直接return了,反之,若是stamp是不可用的,則意味着在讀取的過程當中,可能被其餘線程改寫了數據,所以,有可能出現髒讀,若是若是出現這種狀況,咱們能夠像CAS操做那樣在一個死循環中一直使用樂觀鎖,知道成功爲止
            stamp = s1.readLock();//也能夠升級鎖的級別,這裏咱們升級樂觀鎖的級別,將樂觀鎖變爲悲觀鎖, 若是當前對象正在被修改,則讀鎖的申請可能致使線程掛起.
            try {
                currentX = x;
                currentY = y;
            } finally {
                s1.unlockRead(stamp);//退出臨界區,釋放讀鎖
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}

 

  • StampedLock的小陷阱
  • 有關StampedLock的實現思想
StampedLock的內部實現是基於CLH鎖的,CLH鎖是一種自旋鎖,它保證沒有飢餓的發生,而且能夠保證FIFO(先進先出)的服務順序.
CLH鎖的基本思想以下:鎖維護一個等待線程隊列,全部申請鎖,可是沒有成功的線程都記錄在這個隊列中,每個節點表明一個線程,保存一個標記位(locked).用與判斷當前線程是否已經釋放鎖;locked=true 沒有獲取到鎖,false 已經成功釋放了鎖
     當一個線程視圖得到鎖時,取得等待隊列的尾部節點做爲其前序節點.並使用相似以下代碼判斷前序節點是否已經成功釋放鎖:
while (pred.locked) {
   
}
     只要前序節點(pred)沒有釋放鎖,則表示當前線程還不能繼續執行,所以會自旋等待,
     反之,若是前序線程已經釋放鎖,則當前線程能夠繼續執行.
     釋放鎖時,也遵循這個邏輯,線程會將自身節點的locked位置標記位false,那麼後續等待的線程就能繼續執行了
相關文章
相關標籤/搜索