可重入鎖
可重入鎖:佔有鎖的執行緒可以重新進入.
不僅判斷鎖有沒有被鎖上,還會判斷鎖是誰鎖上的,當就是自己鎖上的時候,那麼他依舊可以再次訪問臨界資源,並把加鎖次數加一。
設計了加鎖次數,以在解鎖的時候,可以確保所有加鎖的過程都解鎖了,其他執行緒才能訪問。不然沒有加鎖的參考值,也就不知道什麼時候解鎖?解鎖多少次?才能保證本執行緒已經訪問完臨界資源了可以喚醒其他執行緒訪問了。實現相對複雜。
廣義上的可重入鎖指的是可重複可遞迴呼叫的鎖,在外層使用鎖之後,在內層仍然可以使用,並且不發生死鎖(前提得是同一個物件或者class),這樣的鎖就叫做可重入鎖。
在java 中,synchronized和java.util.concurrent.locks.ReentrantLock是可重入鎖。
可重入鎖在只要是同一執行緒的情況下,就可以重新進入,即使呼叫不同的方法, 其臨界資源也是安全的.
可重入鎖可以理解為我們常用的物件鎖的升級版
Object lock = new Object();
public void method() {
synchronized(lock) {
...
}
}
而不可重入鎖, 即使是同一執行緒,一旦某方法佔有了鎖,其他需要鎖的方法也是不能進入的.如果呼叫了其他需要佔用鎖的方法,就會造成死鎖.
可重入鎖中維護了一個private volatile int state來計數重入次數,在執行每次操作之前,判斷當前鎖持有者是否是當前物件,採用state計數,不用頻繁的持有釋放操作,這樣既提升了效率,又避免了死鎖。
在 java 併發包中有一些併發框架也使用了自旋 CAS 的方式來實現原子操作,比如 LinkedTransferQueue 類的 Xfer 方法。CAS 雖然很高效的解決原子操作,但是 CAS 仍然存在三大問題。ABA 問題,迴圈時間長開銷大和只能保證一個共享變數的原子操作。
- 1.ABA 問題。因為 CAS 需要在操作值的時候檢查下值有沒有發生變化,如果沒有發生變化則更新,但是如果一個值原來是 A,變成了 B,又變成了 A,那麼使用 CAS 進行檢查時會發現它的值沒有發生變化,但是實際上卻變化了。ABA 問題的解決思路就是使用版本號。在變數前面追加上版本號,每次變數更新的時候把版本號加一,那麼 A-B-A 就會變成 1A-2B-3A。
從 Java1.5 開始 JDK 的 atomic 包裡提供了一個類 AtomicStampedReference 來解決 ABA 問題。這個類的 compareAndSet 方法作用是首先檢查當前引用是否等於預期引用,並且當前標誌是否等於預期標誌,如果全部相等,則以原子方式將該引用和該標誌的值設定為給定的更新值。 - 2.迴圈時間長開銷大。自旋 CAS 如果長時間不成功,會給 CPU 帶來非常大的執行開銷。如果 JVM 能支援處理器提供的 pause 指令那麼效率會有一定的提升,pause 指令有兩個作用,第一它可以延遲流水線執行指令(de-pipeline), 使 CPU 不會消耗過多的執行資源,延遲的時間取決於具體實現的版本,在一些處理器上延遲時間是零。第二它可以避免在退出迴圈的時候因記憶體順序衝突(memory order violation)而引起 CPU 流水線被清空(CPU pipeline flush),從而提高 CPU 的執行效率。
- 3.只能保證一個共享變數的原子操作。當對一個共享變數執行操作時,我們可以使用迴圈 CAS 的方式來保證原子操作,但是對多個共享變數操作時,迴圈 CAS 就無法保證操作的原子性,這個時候就可以用鎖,或者有一個取巧的辦法,就是把多個共享變數合併成一個共享變數來操作。比如有兩個共享變數 i=2,j=a,合併一下 ij=2a,然後用 CAS 來操作 ij。從 Java1.5 開始 JDK 提供了 AtomicReference 類來保證引用物件之間的原子性,你可以把多個變數放在一個物件裡來進行 CAS 操作。
相關文章
- 可重入鎖與不可重入鎖理解
- 死鎖和可重入鎖
- redis分散式鎖-可重入鎖Redis分散式
- 可重入鎖原始碼分析原始碼
- Golang可重入鎖的實現Golang
- Redisson 分散式鎖原始碼 01:可重入鎖加鎖Redis分散式原始碼
- ReentrantLock可重入鎖——原始碼詳解ReentrantLock原始碼
- ZooKeeper 分散式鎖 Curator 原始碼 01:可重入鎖分散式原始碼
- Java併發-顯式鎖篇【可重入鎖+讀寫鎖】Java
- Redis實現可重入的分散式鎖Redis分散式
- Go 為什麼不支援可重入鎖?Go
- java中如何實現可重入的自旋鎖Java
- ReentrantLock可重入鎖、公平鎖非公平鎖區別與實現原理ReentrantLock
- ZooKeeper 分散式鎖 Curator 原始碼 03:可重入鎖併發加鎖分散式原始碼
- Java 種15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖等等Java
- Java 種15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖等等...Java
- 【Java面試】什麼是可重入,什麼是可重入鎖? 它用來解決什麼問題?Java面試
- 重入鎖的理解
- ZooKeeper 分散式鎖 Curator 原始碼 02:可重入鎖重複加鎖和鎖釋放分散式原始碼
- 【java併發程式設計】ReentrantLock 可重入讀寫鎖Java程式設計ReentrantLock
- 【Java】深入理解ReentrantLock可重入鎖之簡單使用JavaReentrantLock
- Lock鎖之重入鎖與讀寫鎖
- java重入鎖、公平鎖和非公平鎖Java
- synchronized鎖重入問題synchronized
- Java 中15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖,樂觀鎖,分段鎖,自旋鎖等等Java
- Java併發基礎-鎖的使用及原理(可重入鎖、讀寫鎖、內建鎖、訊號量等)Java
- Java 重入鎖 ReentrantLock 原理分析JavaReentrantLock
- Lock介面、重入鎖ReentrantLock、讀寫鎖ReentrantReadWriteLockReentrantLock
- AQS學習(二) AQS互斥模式與ReenterLock可重入鎖原理解析AQS模式
- 自旋鎖、阻塞鎖、可重入鎖、悲觀鎖、樂觀鎖、讀寫鎖、偏向所、輕量級鎖、重量級鎖、鎖膨脹、物件鎖和類鎖物件
- 淺談Java中的鎖:Synchronized、重入鎖、讀寫鎖Javasynchronized
- 併發程式設計系列之Lock鎖可重入性與公平性程式設計
- ReentrantLock可重入、可打斷、Condition原理剖析ReentrantLock
- Springboot基於Redisson實現Redis分散式可重入鎖【案例到原始碼分析】Spring BootRedis分散式原始碼
- Java併發包原始碼學習系列:ReentrantLock可重入獨佔鎖詳解Java原始碼ReentrantLock
- 從原始碼入手詳解ReentrantLock,一個比synchronized更強大的可重入鎖原始碼ReentrantLocksynchronized
- [Java併發]AQS的可重入性JavaAQS
- 多執行緒高併發程式設計(2) -- 可重入鎖介紹和自定義執行緒程式設計