顯示鎖

ReentrantLock并不是一種代替內(nèi)置加鎖的方法,而是當(dāng)內(nèi)置加鎖機(jī)制不適用時(shí)的一種可選擇的高級(jí)功能癌幕。

1. Lock與ReentrantLock

Lock提供了一種無條件的兆蕉、可輪詢的、定時(shí)的以及可中斷的鎖獲取操作芋酌,所以加鎖操作和解鎖的方法都是顯式的。

public interface Lock{
  void lock();
  void lockInterruptibly() throws InterruptrdException;
  boolean tryLock();
  boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException;
  void unlock();
  Condition newCondition();
}

ReentrantLock實(shí)現(xiàn)了Lock接口雁佳,并提供了與synchronized相同的互斥性和內(nèi)存可見性脐帝。它還支持在Lock中定義的所有的獲取鎖的模式,并且與synchronized相比糖权,它還為處理鎖的不可用性問題提供了更高的靈活性堵腹。

內(nèi)置鎖在功能上的局限性:

無法中斷一個(gè)正在等待獲取鎖的線程,或者無法在請(qǐng)求一個(gè)鎖時(shí)無限的等下去...

  • 優(yōu)點(diǎn):由于內(nèi)置鎖必須在獲取該鎖的代碼塊中釋放星澳,從而簡(jiǎn)化了編碼工作疚顷,并且與異常交互的很好
  • 無法實(shí)現(xiàn)非阻塞結(jié)構(gòu)的加鎖規(guī)則。
    Lock接口的標(biāo)準(zhǔn)使用方式:
Lock lock=new ReentrantLock();
...
lock.lock();
try{
  //更新對(duì)象狀態(tài)
  //補(bǔ)貨異常禁偎,在必要時(shí)回復(fù)不變性條件
} finally{
  lock.unlock;
}

該形式比內(nèi)置鎖復(fù)雜一些荡含,必須在finally中釋放鎖。否則會(huì)導(dǎo)致一定的危險(xiǎn)届垫。這個(gè)也是ReentrantLock不能完全替代synchronized的原因释液,容易忘記在fianlly中釋放鎖。

1.1 輪詢鎖與定時(shí)鎖

這兩種鎖的獲取模式都是由tryLock方法實(shí)現(xiàn)的装处,具有更完善的錯(cuò)誤恢復(fù)機(jī)制误债。并且可以避免死鎖的發(fā)生:如果不能獲得所有需要的鎖,可以使用定時(shí)或者輪詢的鎖獲取方式妄迁,從而使你可以重新獲得控制權(quán)寝蹈,它會(huì)釋放已經(jīng)獲得的鎖,然后重新嘗試獲取所有的鎖登淘。
當(dāng)在帶有時(shí)間限制的操作中調(diào)用一個(gè)阻塞方法時(shí)箫老,她會(huì)根據(jù)剩余時(shí)間來提供一個(gè)時(shí)限,如果操作不能在相應(yīng)的時(shí)間內(nèi)給出結(jié)果黔州,程序就會(huì)提前結(jié)束耍鬓。然鵝內(nèi)置鎖很難實(shí)現(xiàn)帶有時(shí)間限制的操作阔籽。

1.2 可中斷的鎖獲取操作

lockInterrutibly方法能夠在獲得鎖的同時(shí)保持對(duì)中斷的響應(yīng),并且由于它處于Lock中牲蜀,因此無需創(chuàng)建其他類型的不可中斷阻塞機(jī)制笆制。


2. 公平性

在ReentrantLock的構(gòu)造函數(shù)中提供了兩種公平性選擇:

  • 創(chuàng)建一個(gè)公平的鎖
    在公平的鎖上,線程將按照它們發(fā)出請(qǐng)求的順序來獲得鎖涣达。
    在公平的鎖中在辆,如果有一個(gè)線程持有這個(gè)鎖或者有其他線程在隊(duì)列中等待這個(gè)鎖,那么新發(fā)出請(qǐng)求的線程將被放入隊(duì)列中度苔。
    適用于持鎖時(shí)間相對(duì)較長(zhǎng)或者請(qǐng)求鎖的平均時(shí)間間隔較長(zhǎng)的情況匆篓。
  • 創(chuàng)建一個(gè)非公平的鎖
    在非公平的鎖上,允許插隊(duì):當(dāng)一個(gè)線程請(qǐng)求非公平的鎖時(shí)寇窑,如果再發(fā)出請(qǐng)求的同時(shí)鸦概,該鎖的狀態(tài)變?yōu)榭捎茫敲丛摼€程將跳過所有的等待線程并獲得這個(gè)鎖疗认。
    在非公平的鎖中,只有當(dāng)鎖被某個(gè)線程持有時(shí)伏钠,新發(fā)出的線程請(qǐng)求才會(huì)被放入到隊(duì)列中横漏。
    在大多數(shù)情況下,非公平的鎖的性能都要高于公平鎖的性能熟掂。
    在競(jìng)爭(zhēng)激烈的情況下缎浇,非公平鎖的性能高于公平鎖性能的原因之一有:
    在恢復(fù)一個(gè)被掛起的線程與該線程真正被執(zhí)行之間存在著嚴(yán)重的延遲!
    E.G.線程A持有一個(gè)鎖赴肚,并且線程B請(qǐng)求這個(gè)鎖素跺,因此B被掛起。A釋放鎖的時(shí)候誉券,B被喚醒指厌,并且嘗試再次獲取這個(gè)鎖。與此同時(shí)踊跟,C也在請(qǐng)求這個(gè)鎖踩验,那么C很有可能在B被完全喚醒之前獲得、使用以及釋放了這個(gè)鎖商玫。從而提高了吞吐量呀箕憾!

3. 在synchronized和ReentrantLock之間進(jìn)行選擇

內(nèi)置鎖仍具備的優(yōu)勢(shì):

  • 為開發(fā)人員熟悉,并且簡(jiǎn)潔緊湊拳昌,還廣為使用袭异。
  • ReentrantLock的危險(xiǎn)性高,僅當(dāng)內(nèi)置鎖不能滿足需求時(shí)炬藤,才會(huì)使用ReentrantLock
  • 在java5.0中御铃,在線程轉(zhuǎn)儲(chǔ)中能給出在哪些調(diào)用幀中獲得了哪些鎖碴里,并能夠檢測(cè)和識(shí)別發(fā)生死鎖的線程。ReentrantLock的非塊結(jié)構(gòu)性仍意味著畅买,獲取鎖的操作不能和特定的幀關(guān)聯(lián)起來并闲。
  • 未來更可能提升的是synchronized的性能

4. 讀-寫鎖

一個(gè)資源可以被多個(gè)讀操作訪問,或者被一個(gè)寫操作訪問谷羞,二者不能同時(shí)進(jìn)行帝火。

public interface ReadWriteLock{
  Lock readLock();
  Lock writeLock();
}

要讀取被ReadWriteLock保護(hù)的數(shù)據(jù),首先必須獲得讀取鎖湃缎,當(dāng)需要修改由ReadWriteLock保護(hù)的數(shù)據(jù)時(shí)犀填,必須先獲得寫入鎖∩のィ看上去兩個(gè)鎖是獨(dú)立的九巡,但是讀取鎖和寫入鎖只不過是讀寫鎖對(duì)象的不同視圖。

ReadWriteLock中一些可選實(shí)現(xiàn):

  • **釋放優(yōu)先 : ** 當(dāng)一個(gè)寫入操作釋放寫入鎖時(shí)蹂季,并且隊(duì)列中同時(shí)存在讀線程和寫線程冕广,那么應(yīng)該優(yōu)先選擇讀線程,寫線程偿洁,還是最先發(fā)出請(qǐng)求的線程撒汉?
  • **讀線程插隊(duì): ** 如果鎖是由讀線程持有,但有寫線程正在等待涕滋,那么新到達(dá)的讀線程能否立即獲得訪問權(quán)睬辐,還是應(yīng)該在寫線程后面等待?如果允許讀線程插入到寫線程前面宾肺,有助于提高并發(fā)性溯饵,但是有可能造成寫線程發(fā)生饑餓問題。
  • **重入性 : ** 讀操作和寫操作是否為可重入的锨用?
  • **降級(jí) : ** 如果一個(gè)線程持有寫入鎖丰刊,那么它能否在不釋放該鎖的情況下獲取讀取鎖?這樣可能會(huì)使得寫入鎖被降級(jí)為讀取鎖增拥,同時(shí)不允許其他寫線程修改被保護(hù)的資源藻三。
  • **升級(jí) : ** 讀取鎖能否優(yōu)先于其他正在等待的讀線程和寫線程而升級(jí)為一個(gè)寫入鎖?

ReentrantReadWriteLock

ReentrantReadWriteLock為這兩種鎖都提供了可重入的加鎖定義跪者。并且在其構(gòu)造函數(shù)內(nèi)可選擇一個(gè)公平鎖或者非公平的鎖(默認(rèn))棵帽。

  • 公平的鎖中:等待時(shí)間最長(zhǎng)的線程優(yōu)先獲得鎖。如果這個(gè)鎖被讀線程持有渣玲,而另一個(gè)線程請(qǐng)求寫入鎖逗概,那么其他讀線程都不能獲取讀取鎖,直到寫線程使用完并且釋放了寫入鎖忘衍。
  • 在非公平的鎖中:線程獲得訪問許可的順序是不確定的逾苫。寫線程可以降級(jí)為讀線程卿城,但是讀線程不能升級(jí)為寫線程(導(dǎo)致死鎖)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铅搓,隨后出現(xiàn)的幾起案子瑟押,更是在濱河造成了極大的恐慌,老刑警劉巖星掰,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件多望,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡氢烘,警方通過查閱死者的電腦和手機(jī)怀偷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來播玖,“玉大人椎工,你說我怎么就攤上這事∈裉ぃ” “怎么了维蒙?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)果覆。 經(jīng)常有香客問我颅痊,道長(zhǎng),這世上最難降的妖魔是什么随静? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任八千,我火速辦了婚禮吗讶,結(jié)果婚禮上燎猛,老公的妹妹穿的比我還像新娘。我一直安慰自己照皆,他們只是感情好重绷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著膜毁,像睡著了一般昭卓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瘟滨,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天候醒,我揣著相機(jī)與錄音,去河邊找鬼杂瘸。 笑死倒淫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的败玉。 我是一名探鬼主播敌土,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼镜硕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了返干?” 一聲冷哼從身側(cè)響起兴枯,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎矩欠,沒想到半個(gè)月后财剖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晚顷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年峰伙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片该默。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瞳氓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出栓袖,到底是詐尸還是另有隱情匣摘,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布裹刮,位于F島的核電站音榜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捧弃。R本人自食惡果不足惜赠叼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望违霞。 院中可真熱鬧嘴办,春花似錦、人聲如沸买鸽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽眼五。三九已至妆艘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間看幼,已是汗流浹背批旺。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诵姜,地道東北人汽煮。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逗物。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搬卒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容