jdk8 新特性之StampedLock鎖

參考《java併發編程之美》

 

對於java8新增的特性來看,主要是

1,接口方法可以提供默認的實現,

2,及函數式編程,

目前大部分說到java8 新特性都會想到以上兩點,卻很少人知道java8 還新增了其他的新特性,今天來聊聊java8 新增的鎖的新特性,StampedLock。

StampedLock是併發包裏面jdk8版本新增的一個鎖,該鎖提供了3種模式的讀寫控制,當調用該鎖的一系列函數時,會返回一個long類型的值,這個變量值我們稱之爲(stamp),這個stamp代表了鎖的狀態。其中try系列獲取鎖的方法,當獲取鎖失敗之後,會返回爲0的stamp值。當調用釋放鎖和轉換鎖的方法時需要傳入獲取鎖時返回的stamp值。

接下來分別介紹StampedLock的三種讀寫模式的鎖。

  • 寫鎖 writeLock

該鎖是一個排它鎖還在獨佔鎖,無論哪個時候只能有一個線程獲取到鎖。排它鎖的特性和概念在這裏就不介紹了,不清楚的可以上網查查。我們都知道ReentrantReadWriteLockd的寫鎖就是一個排它鎖,這裏呢咱們的這個寫鎖類似於ReentrantReadWriteLockd的寫鎖,不同的是怎麼的寫鎖是不可重入鎖。也就是當前沒有線程持有讀鎖或者寫鎖時纔可以獲取到該鎖。

在請求該鎖成功後悔返回一個stamp值用來表示該鎖的版本,當釋放該鎖時需要調用unlockWrite方法並傳遞獲取鎖時獲取到的stamp值。並且它提供了非阻塞的tryWriteLock方法。

  • 悲觀讀鎖ReadLock

是一個共享鎖,在沒有線程獲取獨佔寫鎖的情況下,多個線程可以同時獲取該鎖。如果已經有線程佔有寫鎖,則其他線程獲取該鎖都會被阻塞,這類似於ReentrantReadWriteLock的讀鎖,但是這裏的讀鎖是不可重入鎖。

這裏說悲觀就知道,不言而喻,我們都知道悲觀鎖(不管是寫還是讀操作,都認爲會改變到數據,所以在操作之前都會對數據加上鎖),這裏也是這樣的,會悲觀的認爲其他線程會修改數據,所以需要對數據加鎖。

在請求該鎖成功後會返回一個stamp值來標識該鎖的版本,釋放鎖的時候需要調用unlockRead方法,並傳遞stamp值。並且它提供了非阻塞的tryReadLock方法。

  • 樂觀讀鎖tryOptimisticRead

它是相對於悲觀鎖來說,在操作數據之前沒有通過CAS設置鎖的狀態,僅僅通過位運算測試。如果當前沒有線程獲取寫鎖,則簡單返回一個非0的stamp版本信息,獲取該值之後,在之後的具體操作數據前還需要調用validata方法校驗該stamp值是否已經可用(獲取該stamp值後在具體操作數據之前這段期間有沒有其他線程獲取是否佔有寫鎖,如果是validata會返回0,否則就可以使用該stamp版本來對數據進行操作。),由於沒有tryOptimisticRead並沒有使用CAS設置鎖的狀態。所以不需要顯示的釋放鎖。該鎖適合在讀多寫少的場景。

在保證數據一致上需要複製一份要操作的變量到方法棧。

StampedLock 支持這三種鎖在 定條件下進行相互轉換
例如 long tryConvertTo WriteLock(long tamp 期望把 tamp 標示的鎖升級爲寫鎖 這個函數會在下面
種情況下返回 個有效的 stamp 也就是晉升寫鎖成功)

1.當前鎖已經是寫模式了,

2.當前鎖處於讀模式,並且沒有其他線程是讀鎖模式

3.當前處於樂觀鎖模式,並且當前寫鎖可用。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章