成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

sushi / 2835人閱讀

摘要:所謂的重入,就是當(dāng)本線程想再次獲得鎖,不需要重新申請,它本身就已經(jīng)鎖了,即重入該鎖。如果不為,則表示有線程已經(jīng)占有了??偨Y(jié)回顧下要點(diǎn)是一個(gè)可重入的鎖被當(dāng)前占用的線程重入。

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

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

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

為什么會(huì)允許鎖重入呢?因?yàn)樵摼€程已經(jīng)擁有鎖了,不會(huì)受其他線程干擾,那么里面的共享變量就不會(huì)因?yàn)槎嗑€程執(zhí)行造成線程不安全。相當(dāng)于代碼已經(jīng)在串行執(zhí)行了,沒必要再申請多余的鎖了,而是重入當(dāng)前的鎖。

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

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

現(xiàn)在基于以上的認(rèn)識(shí),來看看ReentrantLock的基本實(shí)現(xiàn)吧。

ReentrantLock概覽

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

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

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

Sync同步器

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

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

先判斷下申請解鎖的線程是否獨(dú)占鎖的線程,否則拋出異常退出。
然后計(jì)算新的state值,用當(dāng)前state減去releases值。對(duì)于state值和releases值到底是多少,這里可以先留個(gè)懸念,但大家可以思考下上面注解的定義也可以大概猜出來。
最后判斷新state值是否為0,為0則沒有線程占用,所以設(shè)當(dāng)前獨(dú)占線程為空,并且更新state。這里更新state值并不需要用CAS原子操作,因?yàn)橹挥幸粋€(gè)線程會(huì)占用這個(gè)鎖,不是這個(gè)線程都異常退出了。

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

NonfairSync

沒啥特別的,直接調(diào)用Sync的方法。也沒做修改。

FairSync

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

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

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

@ReservedStackAccess

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

lock()、tryLock()成員函數(shù)

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

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

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

總結(jié)

回顧下要點(diǎn)

ReentrantLock是一個(gè)可重入的鎖(被當(dāng)前占用的線程重入)。

它有兩種模式公平與非公平,通過NonfairSync和FairSync賦值sync成員變量實(shí)現(xiàn)。

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

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

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

如果覺得還不錯(cuò),請關(guān)注公眾號(hào):Zack說碼

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/77075.html

相關(guān)文章

  • Java 入鎖 ReentrantLock 原理分析

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

    lx1036 評(píng)論0 收藏0
  • J.U.C|可入鎖ReentrantLock

    摘要:二什么是重入鎖可重入鎖,顧名思義,支持重新進(jìn)入的鎖,其表示該鎖能支持一個(gè)線程對(duì)資源的重復(fù)加鎖。將由最近成功獲得鎖,并且還沒有釋放該鎖的線程所擁有??梢允褂煤头椒▉頇z查此情況是否發(fā)生。 一、寫在前面 前幾篇我們具體的聊了AQS原理以及底層源碼的實(shí)現(xiàn),具體參見 《J.U.C|一文搞懂AQS》《J.U.C|同步隊(duì)列(CLH)》《J.U.C|AQS獨(dú)占式源碼分析》《J.U.C|AQS共享式源...

    wangdai 評(píng)論0 收藏0
  • Java線程—ReentrantReadWriteLock源碼閱讀

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

    Ververica 評(píng)論0 收藏0
  • 不可不說的Java“鎖”事

    摘要:本文旨在對(duì)鎖相關(guān)源碼本文中的源碼來自使用場景進(jìn)行舉例,為讀者介紹主流鎖的知識(shí)點(diǎn),以及不同的鎖的適用場景。中,關(guān)鍵字和的實(shí)現(xiàn)類都是悲觀鎖。自適應(yīng)意味著自旋的時(shí)間次數(shù)不再固定,而是由前一次在同一個(gè)鎖上的自旋時(shí)間及鎖的擁有者的狀態(tài)來決定。 前言 Java提供了種類豐富的鎖,每種鎖因其特性的不同,在適當(dāng)?shù)膱鼍跋履軌蛘宫F(xiàn)出非常高的效率。本文旨在對(duì)鎖相關(guān)源碼(本文中的源碼來自JDK 8)、使用場景...

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

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

    LiuRhoRamen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<