工作常用4種Java線程鎖的特點(diǎn)雀哨,性能比較、使用場(chǎng)景

多線程的緣由

在出現(xiàn)了進(jìn)程之后,操作系統(tǒng)的性能得到了大大的提升。雖然進(jìn)程的出現(xiàn)解決了操作系統(tǒng)的并發(fā)問(wèn)題音比,但是人們?nèi)匀徊粷M足,人們逐漸對(duì)實(shí)時(shí)性有了要求氢惋。

使用多線程的理由之一是和進(jìn)程相比洞翩,它是一種非郴纾花銷小,切換快菱农,更”節(jié)儉”的多任務(wù)操作方式。

在Linux系統(tǒng)下柿估,啟動(dòng)一個(gè)新的進(jìn)程必須分配給它獨(dú)立的地址空間循未,建立眾多的數(shù)據(jù)表來(lái)維護(hù)它的代碼段、堆棧段和數(shù)據(jù)段秫舌,這是一種”昂貴”的多任務(wù)工作方式的妖。而在進(jìn)程中的同時(shí)運(yùn)行多個(gè)線程,它們彼此之間使用相同的地址空間足陨,共享大部分?jǐn)?shù)據(jù)嫂粟,啟動(dòng)一個(gè)線程所花費(fèi)的空間遠(yuǎn)遠(yuǎn)小于啟動(dòng)一個(gè)進(jìn)程所花費(fèi)的空間,而且墨缘,線程間彼此切換所需的時(shí)間也遠(yuǎn)遠(yuǎn)小于進(jìn)程間切換所需要的時(shí)間星虹。

file

多線程并發(fā)面臨的問(wèn)題

file

由于多個(gè)線程是共同占有所屬進(jìn)程的資源和地址空間的,那么就會(huì)存在一個(gè)問(wèn)題:

如果多個(gè)線程要同時(shí)訪問(wèn)某個(gè)資源镊讼,怎么處理宽涌?

在Java并發(fā)編程中,經(jīng)常遇到多個(gè)線程訪問(wèn)同一個(gè) 共享資源 蝶棋,這時(shí)候作為開發(fā)者必須考慮如何維護(hù)數(shù)據(jù)一致性卸亮,這就是Java鎖機(jī)制(同步問(wèn)題)的來(lái)源。

Java提供了多種多線程鎖機(jī)制的實(shí)現(xiàn)方式玩裙,常見的有:
  • synchronized
  • ReentrantLock
  • Semaphore
  • AtomicInteger等

每種機(jī)制都有優(yōu)缺點(diǎn)與各自的適用場(chǎng)景兼贸,必須熟練掌握他們的特點(diǎn)才能在Java多線程應(yīng)用開發(fā)時(shí)得心應(yīng)手。

4種Java線程鎖(線程同步)

file
1.synchronized

在Java中synchronized關(guān)鍵字被常用于維護(hù)數(shù)據(jù)一致性吃溅。

synchronized機(jī)制是給共享資源上鎖溶诞,只有拿到鎖的線程才可以訪問(wèn)共享資源,這樣就可以強(qiáng)制使得對(duì)共享資源的訪問(wèn)都是順序的决侈。

Java開發(fā)人員都認(rèn)識(shí)synchronized很澄,使用它來(lái)實(shí)現(xiàn)多線程的同步操作是非常簡(jiǎn)單的,只要在需要同步的對(duì)方的方法颜及、類或代碼塊中加入該關(guān)鍵字甩苛,它能夠保證在同一個(gè)時(shí)刻最多只有一個(gè)線程執(zhí)行同一個(gè)對(duì)象的同步代碼,可保證修飾的代碼在執(zhí)行過(guò)程中不會(huì)被其他線程干擾俏站。使用synchronized修飾的代碼具有原子性和可見性讯蒲,在需要進(jìn)程同步的程序中使用的頻率非常高,可以滿足一般的進(jìn)程同步要求肄扎。

synchronized (obj) {
//方法

…….

}

synchronized實(shí)現(xiàn)的機(jī)理依賴于軟件層面上的JVM墨林,因此其性能會(huì)隨著Java版本的不斷升級(jí)而提高赁酝。

到了Java1.6,synchronized進(jìn)行了很多的優(yōu)化旭等,有適應(yīng)自旋酌呆、鎖消除、鎖粗化搔耕、輕量級(jí)鎖及偏向鎖等隙袁,效率有了本質(zhì)上的提高。在之后推出的Java1.7與1.8中弃榨,均對(duì)該關(guān)鍵字的實(shí)現(xiàn)機(jī)理做了優(yōu)化菩收。

需要說(shuō)明的是,當(dāng)線程通過(guò)synchronized等待鎖時(shí)是不能被Thread.interrupt()中斷的鲸睛,因此程序設(shè)計(jì)時(shí)必須檢查確保合理娜饵,否則可能會(huì)造成線程死鎖的尷尬境地。

最后官辈,盡管Java實(shí)現(xiàn)的鎖機(jī)制有很多種箱舞,并且有些鎖機(jī)制性能也比synchronized高,但還是強(qiáng)烈推薦在多線程應(yīng)用程序中使用該關(guān)鍵字拳亿,因?yàn)閷?shí)現(xiàn)方便褐缠,后續(xù)工作由JVM來(lái)完成,可靠性高风瘦。只有在確定鎖機(jī)制是當(dāng)前多線程程序的性能瓶頸時(shí)队魏,才考慮使用其他機(jī)制,如ReentrantLock等万搔。

2.ReentrantLock

可重入鎖胡桨,顧名思義,這個(gè)鎖可以被線程多次重復(fù)進(jìn)入進(jìn)行獲取操作瞬雹。

ReentantLock繼承接口Lock并實(shí)現(xiàn)了接口中定義的方法昧谊,除了能完成synchronized所能完成的所有工作外,還提供了諸如可響應(yīng)中斷鎖酗捌、可輪詢鎖請(qǐng)求呢诬、定時(shí)鎖等避免多線程死鎖的方法。

Lock實(shí)現(xiàn)的機(jī)理依賴于特殊的CPU指定胖缤,可以認(rèn)為不受JVM的約束尚镰,并可以通過(guò)其他語(yǔ)言平臺(tái)來(lái)完成底層的實(shí)現(xiàn)。在并發(fā)量較小的多線程應(yīng)用程序中哪廓,ReentrantLock與synchronized性能相差無(wú)幾狗唉,但在高并發(fā)量的條件下,synchronized性能會(huì)迅速下降幾十倍涡真,而ReentrantLock的性能卻能依然維持一個(gè)水準(zhǔn)分俯。

因此我們建議在高并發(fā)量情況下使用ReentrantLock肾筐。

ReentrantLock引入兩個(gè)概念:公平鎖與非公平鎖

公平鎖指的是鎖的分配機(jī)制是公平的缸剪,通常先對(duì)鎖提出獲取請(qǐng)求的線程會(huì)先被分配到鎖吗铐。反之,JVM按隨機(jī)杏节、就近原則分配鎖的機(jī)制則稱為不公平鎖唬渗。

ReentrantLock在構(gòu)造函數(shù)中提供了是否公平鎖的初始化方式,默認(rèn)為非公平鎖拢锹。這是因?yàn)橐テ蓿枪芥i實(shí)際執(zhí)行的效率要遠(yuǎn)遠(yuǎn)超出公平鎖萄喳,除非程序有特殊需要卒稳,否則最常用非公平鎖的分配機(jī)制。

ReentrantLock通過(guò)方法lock()與unlock()來(lái)進(jìn)行加鎖與解鎖操作他巨,與synchronized會(huì)被JVM自動(dòng)解鎖機(jī)制不同充坑,ReentrantLock加鎖后需要手動(dòng)進(jìn)行解鎖。為了避免程序出現(xiàn)異常而無(wú)法正常解鎖的情況染突,使用ReentrantLock必須在finally控制塊中進(jìn)行解鎖操作捻爷。通常使用方式如下所示:

Lock lock = new ReentrantLock();
try {

lock.lock();

//…進(jìn)行任務(wù)操作5 }

finally {

lock.unlock();

}

3.Semaphore

上述兩種鎖機(jī)制類型都是“互斥鎖”,學(xué)過(guò)操作系統(tǒng)的都知道份企,互斥是進(jìn)程同步關(guān)系的一種特殊情況也榄,相當(dāng)于只存在一個(gè)臨界資源,因此同時(shí)最多只能給一個(gè)線程提供服務(wù)司志。但是甜紫,在實(shí)際復(fù)雜的多線程應(yīng)用程序中,可能存在多個(gè)臨界資源骂远,這時(shí)候我們可以借助Semaphore信號(hào)量來(lái)完成多個(gè)臨界資源的訪問(wèn)囚霸。

Semaphore基本能完成ReentrantLock的所有工作,使用方法也與之類似激才,通過(guò)acquire()與release()方法來(lái)獲得和釋放臨界資源拓型。

經(jīng)實(shí)測(cè),Semaphone.acquire()方法默認(rèn)為可響應(yīng)中斷鎖瘸恼,與ReentrantLock.lockInterruptibly()作用效果一致劣挫,也就是說(shuō)在等待臨界資源的過(guò)程中可以被Thread.interrupt()方法中斷。

此外东帅,Semaphore也實(shí)現(xiàn)了可輪詢的鎖請(qǐng)求與定時(shí)鎖的功能揣云,除了方法名tryAcquire與tryLock不同,其使用方法與ReentrantLock幾乎一致冰啃。Semaphore也提供了公平與非公平鎖的機(jī)制邓夕,也可在構(gòu)造函數(shù)中進(jìn)行設(shè)定刘莹。

Semaphore的鎖釋放操作也由手動(dòng)進(jìn)行,因此與ReentrantLock一樣焚刚,為避免線程因拋出異常而無(wú)法正常釋放鎖的情況發(fā)生点弯,釋放鎖的操作也必須在finally代碼塊中完成。

4.AtomicInteger

首先說(shuō)明矿咕,此處AtomicInteger是一系列相同類的代表之一抢肛,常見的還有AtomicLong、AtomicLong等碳柱,他們的實(shí)現(xiàn)原理相同捡絮,區(qū)別在與運(yùn)算對(duì)象類型的不同。

我們知道莲镣,在多線程程序中福稳,諸如++i

i++等運(yùn)算不具有原子性,是不安全的線程操作之一瑞侮。通常我們會(huì)使用synchronized將該操作變成一個(gè)原子操作的圆,但JVM為此類操作特意提供了一些同步類,使得使用更方便半火,且使程序運(yùn)行效率變得更高越妈。通過(guò)相關(guān)資料顯示,通常AtomicInteger的性能是ReentantLock的好幾倍钮糖。

Java線程鎖總結(jié)

** 1.synchronized:**

在資源競(jìng)爭(zhēng)不是很激烈的情況下梅掠,偶爾會(huì)有同步的情形下,synchronized是很合適的店归。原因在于阎抒,編譯程序通常會(huì)盡可能的進(jìn)行優(yōu)化synchronize,另外可讀性非常好娱节。

** 2.ReentrantLock:**

在資源競(jìng)爭(zhēng)不激烈的情形下挠蛉,性能稍微比synchronized差點(diǎn)點(diǎn)。但是當(dāng)同步非常激烈的時(shí)候肄满,synchronized的性能一下子能下降好幾十倍谴古,而ReentrantLock確還能維持常態(tài)。

高并發(fā)量情況下使用ReentrantLock稠歉。

** 3.Atomic:**

和上面的類似掰担,不激烈情況下,性能比synchronized略遜怒炸,而激烈的時(shí)候带饱,也能維持常態(tài)。激烈的時(shí)候,Atomic的性能會(huì)優(yōu)于ReentrantLock一倍左右勺疼。但是其有一個(gè)缺點(diǎn)教寂,就是只能同步一個(gè)值,一段代碼中只能出現(xiàn)一個(gè)Atomic的變量执庐,多于一個(gè)同步無(wú)效酪耕。因?yàn)樗荒茉诙鄠€(gè)Atomic之間同步。

所以轨淌,我們寫同步的時(shí)候迂烁,優(yōu)先考慮synchronized,如果有特殊需要递鹉,再進(jìn)一步優(yōu)化盟步。ReentrantLock和Atomic如果用的不好,不僅不能提高性能躏结,還可能帶來(lái)災(zāi)難却盘。

如何一起學(xué)習(xí),有沒有免費(fèi)資料窜觉?

file

本文由博客一文多發(fā)平臺(tái) OpenWrite 發(fā)布谷炸!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末北专,一起剝皮案震驚了整個(gè)濱河市禀挫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拓颓,老刑警劉巖语婴,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異驶睦,居然都是意外死亡砰左,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門场航,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)缠导,“玉大人,你說(shuō)我怎么就攤上這事溉痢∑г欤” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵孩饼,是天一觀的道長(zhǎng)髓削。 經(jīng)常有香客問(wèn)我,道長(zhǎng)镀娶,這世上最難降的妖魔是什么立膛? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮梯码,結(jié)果婚禮上宝泵,老公的妹妹穿的比我還像新娘好啰。我一直安慰自己,他們只是感情好儿奶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布坎怪。 她就那樣靜靜地躺著,像睡著了一般廓握。 火紅的嫁衣襯著肌膚如雪搅窿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天隙券,我揣著相機(jī)與錄音男应,去河邊找鬼。 笑死娱仔,一個(gè)胖子當(dāng)著我的面吹牛沐飘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播牲迫,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼耐朴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了盹憎?” 一聲冷哼從身側(cè)響起筛峭,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎陪每,沒想到半個(gè)月后影晓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡檩禾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年挂签,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盼产。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饵婆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出戏售,到底是詐尸還是另有隱情侨核,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布蜈项,位于F島的核電站芹关,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏紧卒。R本人自食惡果不足惜侥衬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧轴总,春花似錦直颅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至往堡,卻和暖如春械荷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背虑灰。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工吨瞎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人穆咐。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓颤诀,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親对湃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子崖叫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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