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

資訊專欄INFORMATION COLUMN

Java多線程——重入鎖ReentrantLock源碼閱讀

sushi / 2837人閱讀

摘要:所謂的重入,就是當本線程想再次獲得鎖,不需要重新申請,它本身就已經鎖了,即重入該鎖。如果不為,則表示有線程已經占有了。總結回顧下要點是一個可重入的鎖被當前占用的線程重入。

上一章《AQS源碼閱讀》講了AQS框架,這次講講它的應用類(注意不是子類實現,待會細講)。
ReentrantLock,顧名思義重入鎖,但什么是重入,這個鎖到底是怎樣的,我們來看看類的注解說明

ReentrantLock與隱式鎖synchronized功能相同,但ReentrantLock更具有擴展性。
《鎖優化》里提到Java在1.6對隱式鎖synchronized做了鎖的優化,使其性能與顯式鎖性能相差無異。所以在兩者的選擇上,更多的是考慮用法,以及功能上的擴展。

ReentrantLock是線程獨占的,不能與其他線程共享。所謂的重入,就是當本線程想再次獲得鎖,不需要重新申請,它本身就已經鎖了,即重入該鎖。

為什么會允許鎖重入呢?因為該線程已經擁有鎖了,不會受其他線程干擾,那么里面的共享變量就不會因為多線程執行造成線程不安全。相當于代碼已經在串行執行了,沒必要再申請多余的鎖了,而是重入當前的鎖。

ReentrantLock會提供一個公平鎖的模式,如果選擇這個模式,會盡量使得獲取鎖是公平的,先來先得,但不一定嚴格按順序。

如果選擇了公平鎖,性能上會比不使用(默認)低一些。沒有一定保證順序,同時也降性能,所以如果沒有特別的要求,盡量使用默認的非公平鎖。

現在基于以上的認識,來看看ReentrantLock的基本實現吧。

ReentrantLock概覽

ReentrantLock是實現Lock接口的。所以主要的方法就是Lock接口定義的方法,包括lock()、tryLock()、unlock()、newCondition()等。

lock()與tryLock()的區別就是前者會一直等到直到獲取鎖,后者則是嘗試在當時獲取鎖,不會重復去申請獲取。
這個newCondition()感覺比較突兀,看起來完全不了解有什么用,和Lock有什么關系,我們后面再詳細了解。

ReentrantLock里面有一個最核心的成員變量,sync。sync的類型就是內部類Sync。它是AQS的子類,也就是說它就是實現ReentrantLock同步的工具。而FairSync和unFairSync則是Sync的子類,封裝了是否公平的功能,用于賦值給sync成員變量。

Sync同步器

Sync是繼承上文所介紹的AQS,是ReentrantLock里面的NonfairSync和FairSync的父類。
看注解可以知道,Sync用了AQS的state(狀態原子值)來標識鎖被持有的數量。

在AQS中,tryRelease()是沒有定義的,所以在Sync中重寫了。

先判斷下申請解鎖的線程是否獨占鎖的線程,否則拋出異常退出。
然后計算新的state值,用當前state減去releases值。對于state值和releases值到底是多少,這里可以先留個懸念,但大家可以思考下上面注解的定義也可以大概猜出來。
最后判斷新state值是否為0,為0則沒有線程占用,所以設當前獨占線程為空,并且更新state。這里更新state值并不需要用CAS原子操作,因為只有一個線程會占用這個鎖,不是這個線程都異常退出了。

AQS中核心的tryAcquire()方法并沒有在這里實現,因為子類NonfaiSync和FairSync的實現并不一樣。但這里同樣需要用到nonfairTryAcquire,所以抽象出來了。但為什么同樣需要,暫時不得而知,帶著問題后面再看看。
先判斷當前鎖的state是否為0,為0則表示沒人獲取,然后通過CAS更新為acquires值(依然不知道值是多少),同時更新當前線程為鎖的獨占線程。
如果state不為0,則表示有線程已經占有了。但可能占有的線程是當前線程,那么當前的state會加上acquires值。
這里很容易就看出來state就是代表重入的次數!所以上面的謎題就解開了,releases,aquires都是代表每次申請的值,在ReentrantLock肯定都是1,他們的計算總值就是原子值state。
如果state不為0,也不是被當前線程占用,那么返回false獲取失敗。

NonfairSync

沒啥特別的,直接調用Sync的方法。也沒做修改。

FairSync

公平鎖的同步器。只有當遞歸調用或者沒有其他等待者,再或者他自己本身排第一才能獲取鎖。
這話比較繞口,大概意思應該是不停地輪詢申請鎖,直到自己排到隊列的第一才能獲取。

乍看一看,這個方法基本和父類Sync的nonfairTryAcquire()一樣,唯一不同點就是在沒有線程占用的時候(state=0),多了個!hasQueuedPredecessors()前置判斷。

這個方法用來判斷是否隊列為空,或者當前線程是否在隊列的最前面。
所以公平鎖模式下,想要能獲取鎖,除非自己排在隊列的最前面。
綜上看,FairSync根本沒有調用到nonfairTryAcquire(),為何說子類都需要用到呢?繼續留著懸念,后面解答。

@ReservedStackAccess

可以看到上面介紹的tryAcquire()和tryRelease()都有@ReservedStackAccess。這個注解到底有什么用?
查找了下資料,這個是JEP 270添加的新注解。它會保護被注解的方法,通過添加一些額外的空間,防止在多線程運行的時候出現棧溢出。具體看下圖

lock()、tryLock()成員函數

ReentrantLock里面的lock()方法是調用成員變量sync的acquire()。
無論是否公平鎖都是直接調用AQS的acquire()方法,不過就是各自有tryAcuqire()的重寫,即上文所說的內容。
參數1,是透傳給tryAcquire()的,所以這里代表是入鎖一次的意思。

而tryLock()調用的是成員變量sync的nonfairTryAcquire()。上文說到Sync內部類抽象了這個方法出來,說到子類都會用到,說的正是tryLock()方法需要用到。
所以顯而易見的,無論是否公平鎖,調用tryLock()都是用的非公平鎖的方法。為什么呢?
因為tryLock()的try只是嘗試,無論是否公平,對于方法來說沒有必要,只是嘗試申請的時候能否獲取鎖而已。

至于其他成員函數,大都是圍繞獲取線程和隊列的狀態,沒什么特別的,在這里不再贅述,有興趣的可以看看源碼。

總結

回顧下要點

ReentrantLock是一個可重入的鎖(被當前占用的線程重入)。

它有兩種模式公平與非公平,通過NonfairSync和FairSync賦值sync成員變量實現。

兩種模式都是AQS的子類,通過重寫tryAcquire()區別不同。公平鎖多了是否在隊列的頭的判斷。

tryLock()方法沒有區分模式,都是一樣的。

上文提到的newCondition()還沒有涉及到,等后續再起一章節說下這個Condition。

如果覺得還不錯,請關注公眾號:Zack說碼

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77075.html

相關文章

  • Java 入鎖 ReentrantLock 原理分析

    摘要:的主要功能和關鍵字一致,均是用于多線程的同步。而僅支持通過查詢當前線程是否持有鎖。由于和使用的是同一把可重入鎖,所以線程可以進入方法,并再次獲得鎖,而不會被阻塞住。公平與非公平公平與非公平指的是線程獲取鎖的方式。 1.簡介 可重入鎖ReentrantLock自 JDK 1.5 被引入,功能上與synchronized關鍵字類似。所謂的可重入是指,線程可對同一把鎖進行重復加鎖,而不會被阻...

    lx1036 評論0 收藏0
  • J.U.C|可入鎖ReentrantLock

    摘要:二什么是重入鎖可重入鎖,顧名思義,支持重新進入的鎖,其表示該鎖能支持一個線程對資源的重復加鎖。將由最近成功獲得鎖,并且還沒有釋放該鎖的線程所擁有。可以使用和方法來檢查此情況是否發生。 一、寫在前面 前幾篇我們具體的聊了AQS原理以及底層源碼的實現,具體參見 《J.U.C|一文搞懂AQS》《J.U.C|同步隊列(CLH)》《J.U.C|AQS獨占式源碼分析》《J.U.C|AQS共享式源...

    wangdai 評論0 收藏0
  • Java線程—ReentrantReadWriteLock源碼閱讀

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

    Ververica 評論0 收藏0
  • 不可不說的Java“鎖”事

    摘要:本文旨在對鎖相關源碼本文中的源碼來自使用場景進行舉例,為讀者介紹主流鎖的知識點,以及不同的鎖的適用場景。中,關鍵字和的實現類都是悲觀鎖。自適應意味著自旋的時間次數不再固定,而是由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態來決定。 前言 Java提供了種類豐富的鎖,每種鎖因其特性的不同,在適當的場景下能夠展現出非常高的效率。本文旨在對鎖相關源碼(本文中的源碼來自JDK 8)、使用場景...

    galaxy_robot 評論0 收藏0
  • 到底什么是入鎖,拜托,一次搞清楚!

    摘要:為什么叫重入鎖呢,我們把它拆開來看就明了了。釋放鎖,每次鎖持有者數量遞減,直到為止。 相信大家在工作或者面試過程中經常聽到重入鎖這個概念,或者與關鍵字 synchrozied 的對比,棧長面試了這么多人,80%的面試者都沒有答對或沒有答到點上,或者把雙重效驗鎖搞混了,哭笑不得。。 那么你對重入鎖了解有多少呢?今天,棧長幫大家撕開重入鎖的面紗,來見識下重入鎖的真實容顏。。 什么是重入鎖 ...

    LiuRhoRamen 評論0 收藏0

發表評論

0條評論

sushi

|高級講師

TA的文章

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