“鎖”的性能和優(yōu)化

一罕袋、死鎖

關(guān)于死鎖改淑,無(wú)外乎,對(duì)線程資源的爭(zhēng)搶浴讯,線程之間相互等待對(duì)方釋放資源朵夏,從而導(dǎo)致等待的一種情況。

出現(xiàn)死鎖的條件在于:
①互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用
②請(qǐng)求和保持條件:一個(gè)線程因?yàn)檎?qǐng)求資源的時(shí)候?qū)е伦枞芘Γ簿褪菬o(wú)法請(qǐng)求到其他資源的時(shí)候仰猖,自身阻塞,但是又無(wú)法釋放自己所擁有的資源奈籽,從而使其他想要獲取其資源的線程繼續(xù)等待饥侵。
③不剝奪條件:對(duì)于一個(gè)擁有某個(gè)資源的線程,如果這個(gè)線程沒(méi)有完成其自身的工作衣屏,那么躏升,其他線程無(wú)法強(qiáng)行剝奪。
④循環(huán)等待關(guān)系:一系列線程之間形成相互等待的一種循環(huán)等待資源的關(guān)系狼忱。

二膨疏、線程狀態(tài)

首先得知道線程的狀態(tài):
①新建狀態(tài)(New) 新創(chuàng)建了一個(gè)線程對(duì)象。
②就緒狀態(tài)(Runnable) 線程對(duì)象創(chuàng)建后钻弄,其他線程調(diào)用了該對(duì)象的start()方法佃却。該狀態(tài)的線程位于可運(yùn)行線程池中,變得可運(yùn)行窘俺,等待獲取CPU的使用權(quán)饲帅。
③運(yùn)行狀態(tài)(Running) 就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼批销。
④阻塞狀態(tài)(Blocked) 阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán)洒闸,暫時(shí)停止運(yùn)行。直到線程進(jìn)入就緒狀態(tài)均芽,才有機(jī)會(huì)轉(zhuǎn)到運(yùn)行狀態(tài)丘逸。阻塞的情況分三種:

-------等待阻塞:運(yùn)行的線程執(zhí)行wait()方法,JVM會(huì)把該線程放入等待池中掀宋。
-------同步阻塞:運(yùn)行的線程在獲取對(duì)象的同步鎖時(shí)深纲,若該同步鎖被別的線程占用,則JVM會(huì)把該線程放入鎖池中劲妙。
-------其他阻塞:運(yùn)行的線程執(zhí)行sleep()或join()方法湃鹊,或者發(fā)出了I/O請(qǐng)求時(shí),JVM會(huì)把該線程置為阻塞狀態(tài)镣奋。當(dāng)sleep()狀態(tài)超時(shí)币呵、join()等待線程終止或者超時(shí)、或者I/O處理完畢時(shí)侨颈,線程重新轉(zhuǎn)入就緒狀態(tài)余赢。
⑤死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法芯义,該線程結(jié)束生命周期

其狀態(tài)變化過(guò)程:

當(dāng)執(zhí)行new Thread(Runnabler)后,新創(chuàng)建出來(lái)的線程處于new狀態(tài)妻柒,這種線程不可能執(zhí)行扛拨。
當(dāng)執(zhí)行thread.start()后,線程處于runnable狀態(tài)举塔,這種情況下只要得CPU绑警,就可以開(kāi)始執(zhí)行了。runnable狀態(tài)的線程央渣,會(huì)接受JVM的調(diào)度计盒,進(jìn)入running狀態(tài),但是具體何時(shí)會(huì)進(jìn)入這個(gè)狀態(tài)痹屹,是隨機(jī)不可知的running狀態(tài)中的線程最為復(fù)雜章郁,可能會(huì)進(jìn)入runnable、waiting志衍、timed_waiting暖庄、blocked、dead狀態(tài):如果CPU調(diào)度給了別的線程楼肪,或者執(zhí)行了Thread.yield()方法培廓,則進(jìn)入runnable狀態(tài),但是也有可能立刻又進(jìn)入running狀態(tài)如果執(zhí)行了Thread.sleep(long)春叫,或者thread.join(long)肩钠,或者在鎖對(duì)象上調(diào)用object.wait(long)方法,則會(huì)進(jìn)入timed_waiting狀態(tài)如果執(zhí)行thread.join()暂殖,或者在鎖對(duì)象上調(diào)用了object.wait()方法价匠,則會(huì)進(jìn)入waiting狀態(tài)如果進(jìn)入了同步方法或者同步代碼塊,沒(méi)有獲取鎖對(duì)象的話呛每,則會(huì)進(jìn)入blocked狀態(tài)
處于waiting狀態(tài)中的線程踩窖,如果是因?yàn)閠hread.join()方法進(jìn)入等待的,在目標(biāo)thread執(zhí)行完畢之后晨横,會(huì)回到runnable狀態(tài)洋腮;如果是因?yàn)閛bject.wait()方法進(jìn)入等待的話,在鎖對(duì)象執(zhí)行object.notify()或者object.notifyAll()之后會(huì)回到runnable狀態(tài)手形,處于timed_waiting狀態(tài)中的線程啥供,和waiting狀態(tài)中的差不多,只不過(guò)是設(shè)定時(shí)間到了库糠,就會(huì)回到runnable狀態(tài)處于blocked狀態(tài)中的線程伙狐,只有獲取了鎖之后,才會(huì)脫離阻塞狀態(tài)。當(dāng)線程執(zhí)行完畢鳞骤,或者拋出了未捕獲的異常之后窒百,會(huì)進(jìn)入dead狀態(tài)黍判,該線程結(jié)束豫尽。

三、常見(jiàn)鎖的優(yōu)化

(一)代碼層面

1顷帖、減少鎖持有的時(shí)間
比如:

public  synchronized void syncMethod(){
         othercode1();
         mutextMethod();
         othercode2();
}

實(shí)際的更新操作是在mutextMethod()方法美旧,所以對(duì)整個(gè)方法加鎖并沒(méi)有必要。
所以贬墩,為了減少鎖持有的時(shí)間榴嗅,可以只將mutextMethod()加類鎖,作用域當(dāng)前實(shí)例對(duì)象陶舞;

public  void syncMethod(){
         othercode1();
         synchronize(this){
               mutextMethod();
         }
         othercode2();
}

2嗽测、減小鎖的顆粒度
即只鎖住相關(guān)容易造成并發(fā)錯(cuò)誤的地方,同時(shí)又要實(shí)現(xiàn)線程安全肿孵,concurrentHashMap 與 hashMap之間即實(shí)現(xiàn)了減小鎖的顆粒度的一個(gè)優(yōu)化唠粥。

**:對(duì)于concurrentHashMap有一個(gè)重要的點(diǎn),concurrentHashMap的size()方法停做,會(huì)優(yōu)先使用無(wú)鎖的方式來(lái)求和晤愧,但是如果失敗則會(huì)嘗試取得所有“子段”的鎖,所以蛉腌,在高并發(fā)場(chǎng)合官份,concurrentHashMap的size()方法性能要比hashMap的性能要差。

3烙丛、鎖分離(讀寫分離鎖)
即對(duì)功能的劃分加鎖舅巷,比如讀寫分離鎖,讀讀不互斥河咽,讀寫互斥钠右,寫寫互斥。

4库北、鎖粗化
如果對(duì)一個(gè)鎖爬舰,不停的獲取和釋放,其本身也會(huì)消耗系統(tǒng)資源寒瓦,所以對(duì)于一連串的對(duì)同一個(gè)對(duì)象進(jìn)行加鎖情屹,倒不如將這段合在一起加鎖。這即鎖的粗化杂腰。

(二)JVM層面

1垃你、自旋鎖
在多線程并發(fā)條件下,頻繁的掛起和恢復(fù)線程的操作會(huì)給系統(tǒng)帶來(lái)極大的壓力,特別是當(dāng)訪問(wèn)共享資源僅需要花費(fèi)很小一段CPU時(shí)間時(shí)候惜颇,為了這段時(shí)間去做重量級(jí)的線程切換是不值得的皆刺。

自旋鎖就是可以使線程在沒(méi)有取得鎖的時(shí)候,不被掛起凌摄,而轉(zhuǎn)而去執(zhí)行一個(gè)空循環(huán)(即所謂的自旋)羡蛾,在若干個(gè)空循環(huán)后,線程如果獲得了鎖锨亏,則繼續(xù)執(zhí)行痴怨,若線程依然不能獲得鎖,才會(huì)被掛起器予。

當(dāng)然自旋鎖不適用與競(jìng)爭(zhēng)激烈浪藻,單線程鎖占用時(shí)間長(zhǎng)的并發(fā)程序。

JAVA虛擬機(jī)提供: -XX:+UseSinning參數(shù)來(lái)開(kāi)啟自旋鎖乾翔,使用
-XX:PreBlockSpin參數(shù)來(lái)設(shè)置自旋鎖的等待次數(shù)爱葵。

2、鎖消除
鎖消除是JVM在即時(shí)編譯時(shí)反浓,通過(guò)對(duì)運(yùn)行上下文的掃描萌丈,去除不可能存在共享資源競(jìng)爭(zhēng)的鎖,通過(guò)鎖消除勾习,可以節(jié)省毫無(wú)意義的請(qǐng)求時(shí)間浓瞪。

JVM虛擬機(jī)可以在運(yùn)行時(shí)基于逃逸分析技術(shù),捕獲到這些不可能存在競(jìng)爭(zhēng)卻有申請(qǐng)鎖的代碼段巧婶,并消除這些不必要的鎖乾颁,從而提高性能。
比如下面這段代碼:

protected  String  craeteStringBuffer(String a , String  b){
          StringBuffer  sb = new  StringBuffer();  //局部變量艺栈,沒(méi)有逃逸出這個(gè)方法
          sb.append(a);   //append()中有鎖的申請(qǐng)英岭,但是在當(dāng)前環(huán)境下是沒(méi)有必要的
          sb.append(b);
          return   sb.toString();  
}

逃逸分析和鎖消除分別可以使用JVM參數(shù) -XX:+DoEscapeAnalysis 和 -XX:+EliminateLocks開(kāi)啟(鎖消除必須工作在server模式下)

使用參數(shù) -server -XX:-DoEscapeAnalysis -XX:EliminateLocks關(guān)閉逃逸分析和鎖消除。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末湿右,一起剝皮案震驚了整個(gè)濱河市诅妹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毅人,老刑警劉巖吭狡,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異丈莺,居然都是意外死亡划煮,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門缔俄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弛秋,“玉大人器躏,你說(shuō)我怎么就攤上這事⌒仿裕” “怎么了登失?”我有些...
    開(kāi)封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)挖炬。 經(jīng)常有香客問(wèn)我揽浙,道長(zhǎng),這世上最難降的妖魔是什么茅茂? 我笑而不...
    開(kāi)封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任捏萍,我火速辦了婚禮,結(jié)果婚禮上空闲,老公的妹妹穿的比我還像新娘。我一直安慰自己走敌,他們只是感情好碴倾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著掉丽,像睡著了一般跌榔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捶障,一...
    開(kāi)封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天僧须,我揣著相機(jī)與錄音,去河邊找鬼项炼。 笑死担平,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锭部。 我是一名探鬼主播暂论,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拌禾!你這毒婦竟也來(lái)了取胎?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤湃窍,失蹤者是張志新(化名)和其女友劉穎闻蛀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體您市,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡觉痛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了墨坚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秧饮。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡映挂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盗尸,到底是詐尸還是另有隱情柑船,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布泼各,位于F島的核電站鞍时,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏扣蜻。R本人自食惡果不足惜逆巍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望莽使。 院中可真熱鬧锐极,春花似錦、人聲如沸芳肌。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)亿笤。三九已至翎迁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間净薛,已是汗流浹背汪榔。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肃拜,地道東北人痴腌。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像爆班,于是被迫代替她去往敵國(guó)和親衷掷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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

  • 一柿菩、進(jìn)程和線程 進(jìn)程 進(jìn)程就是一個(gè)執(zhí)行中的程序?qū)嵗菪幔總€(gè)進(jìn)程都有自己獨(dú)立的一塊內(nèi)存空間,一個(gè)進(jìn)程中可以有多個(gè)線程枢舶。...
    阿敏其人閱讀 2,612評(píng)論 0 13
  • layout: posttitle: 《Java并發(fā)編程的藝術(shù)》筆記categories: Javaexcerpt...
    xiaogmail閱讀 5,820評(píng)論 1 19
  • 一懦胞、線程狀態(tài)轉(zhuǎn)換新建(New)可運(yùn)行(Runnable)阻塞(Blocking)無(wú)限期等待(Waiting)限期等...
    達(dá)微閱讀 586評(píng)論 1 2
  • 1. cpu通過(guò)時(shí)間片分配算法來(lái)循環(huán)執(zhí)行任務(wù),當(dāng)前任務(wù)執(zhí)行一個(gè)時(shí)間片后會(huì)切換到下一任務(wù)凉泄。但是躏尉,再切換之前會(huì)保存上一...
    冰與河豚魚(yú)閱讀 668評(píng)論 0 0
  • 面對(duì)現(xiàn)在孩子的成長(zhǎng)和教育問(wèn)題,許多的家長(zhǎng)越來(lái)越迷茫后众。矛盾也越來(lái)越突出胀糜,孩子家庭作業(yè)颅拦、補(bǔ)習(xí)班越來(lái)越多,可也越來(lái)越多的...
    天地一沙鷗123閱讀 668評(píng)論 2 9