synchronized至会、鎖、多線程同步的原理是咋樣的

先綜述個結(jié)論:

一般說的synchronized用來做多線程同步功能谱俭,其實synchronized只是提供多線程互斥奉件,而對象的wait()和notify()方法才提供線程的同步功能。

一般說synchronized是加鎖昆著,或者說是加對象鎖县貌,其實對象鎖只是synchronized在實現(xiàn)鎖機制中的一種鎖(重量鎖,用這種方式互斥線程開銷大所以叫重量鎖凑懂,或者叫對象monitor)煤痕,而synchronized的鎖機制會根據(jù)線程競爭情況在運行會有偏向鎖、輕量鎖接谨、對象鎖摆碉,自旋鎖(或自適應(yīng)自旋鎖)等,總之脓豪,synchronized可以認(rèn)為是一個幾種鎖過程的封裝巷帝。


原理

通常說的synchronized在方法或塊上加鎖,這里的鎖就是對象鎖(當(dāng)然也可以在類上面)扫夜,或者叫重量鎖楞泼,在JVM中又叫對象監(jiān)視器(Monitor)驰徊,就是對象來監(jiān)視線程的互斥。

先來回顧一下對象在堆里的邏輯結(jié)構(gòu):

對象在內(nèi)存中的結(jié)構(gòu)看這里》》

對象頭里的結(jié)構(gòu)大致如此:

其中Tag的2bit用來顯示鎖類型堕阔。通常我們說synchronized的對象鎖棍厂,就是這里Tag=10時的monitor對象,這里的Monitor address就是這個monitor對象(就是重量鎖)的地址印蔬。

當(dāng)多個線程同時請求synchronized方法或塊時勋桶,monitor會設(shè)置幾個虛擬邏輯數(shù)據(jù)結(jié)構(gòu)來管理這些多線程。下圖是簡化了的管理結(jié)構(gòu)侥猬。

新請求的線程會首先被加入到線程排隊隊列中例驹,線程阻塞,當(dāng)某個擁有鎖的線程unlock之后退唠,則排隊隊列里的線程競爭上崗(synchronized是不公平競爭鎖鹃锈,下面還會講到)。如果運行的線程調(diào)用對象的wait()后就釋放鎖并進入wait線程集合那邊瞧预,當(dāng)調(diào)用對象的notify()或notifyall()后屎债,wait線程就到排隊那邊。這是大致的邏輯垢油。

同時再看看線程的狀態(tài)圖

Blocked就是阻塞狀態(tài)盆驹。

wait()和sleep()最大的不同在于wait()會釋放對象鎖,而sleep()不會滩愁!wait躯喇、sleep、yield區(qū)別如下:

似乎講到這里硝枉,synchronized鎖和wait()廉丽、notify()來實現(xiàn)多線程同步就完成了。

但是妻味,自旋鎖或自適應(yīng)自旋鎖:

因為線程阻塞后進入排隊隊列和喚醒都需要CPU從用戶態(tài)轉(zhuǎn)為核心態(tài)正压,尤其頻繁的阻塞和喚醒對CPU來說是負(fù)荷很重的工作。同時統(tǒng)計發(fā)現(xiàn)责球,很多對象鎖的鎖定狀態(tài)只會持續(xù)很短的一段時間焦履,例如一個線程切換周期,這樣的話在很短的時間內(nèi)阻塞線程又很快喚醒線程顯然不值得棕诵,所以引入了自旋鎖概念裁良。

所謂“自旋”,就monitor并不把線程阻塞放入排隊隊列校套,而是去執(zhí)行一個無意義的循環(huán)价脾,循環(huán)結(jié)束后看看是否鎖已釋放并直接進行競爭上崗步驟,如果競爭不到繼續(xù)自旋循環(huán)笛匙,循環(huán)過程中線程的狀態(tài)一直處于running狀態(tài)侨把。明顯自旋鎖使得synchronized的對象鎖方式在線程之間引入了不公平犀变。但是這樣可以保證大吞吐率和執(zhí)行效率。

不過雖然自旋鎖方式省去了阻塞線程的時間和空間(隊列的維護等)開銷秋柄,但是長時間自旋也是很低效的获枝。所以自旋的次數(shù)一般控制在一個范圍內(nèi),例如10,50等骇笔,在超出這個范圍后省店,線程就進入排隊隊列。

自適應(yīng)自旋鎖笨触,就是自旋的次數(shù)是通過JVM在運行時收集的統(tǒng)計信息懦傍,動態(tài)調(diào)整自旋鎖的自旋次數(shù)上界。

講到這里似乎synchronized鎖的過程更加豐滿了芦劣。

不過synchronized在運行過程中不是一下子就到對象鎖這個級別的粗俱,它根據(jù)線程競爭情況會經(jīng)過幾次升級變化。這里就出現(xiàn)了另外幾種鎖虚吟。

輕量鎖和偏向鎖

當(dāng)多線程環(huán)境進入synchronized區(qū)域的線程沒競爭時寸认,JVM并不會馬上創(chuàng)建對象鎖,而是用輕量鎖或偏向鎖串慰。

不過需要明確的是偏塞,輕量鎖和偏向鎖,都不能代替重量鎖邦鲫,只不過是在沒有多線程競爭時烛愧,沒必要用重量鎖而無畏的消耗資源。但是一旦出現(xiàn)了多線程競爭時掂碱,synchronized區(qū)域的輕量鎖或偏向鎖都會立即升級為重量鎖。

輕量鎖或偏向鎖使用的條件是進入synchronized區(qū)域時沒有其他任何其他線程在使用慎冤。

這時線程t訪問對象的synchronized區(qū)域時疼燥,對象頭的標(biāo)志位Tag狀態(tài)為01,以及還有1位的偏向信息用于記錄這個對象是否可用偏向鎖蚁堤。然后t在對象上申請輕量鎖時醉者,若偏向信息為0,表明當(dāng)前對象還未加鎖披诗,或加過偏向鎖(加過撬即,注意是加過偏向鎖的對象只能被同樣的線程加鎖,如果不同的線程想要獲取鎖呈队,需要先將偏向鎖升級為輕量鎖剥槐,稍后會講到),在判斷對當(dāng)前對象確實沒有被任何其他線程鎖住后宪摧,即可以在該對象上加輕量鎖粒竖。

加輕量鎖的過程很簡單:在當(dāng)前線程的棧幀(stack?frame)中生成一個鎖記錄(lock?record)颅崩,這個鎖記錄比前面說的那個對象鎖(管理線程隊列的monitor)簡單多了,它只是對象頭的一個拷貝蕊苗。然后把對象頭里的tag改成00沿后,并把這個棧幀里的lock?record地址放入對象頭里。若操作成功朽砰,那就完成了輕量鎖操作尖滚。如果不成功,說明有線程在競爭瞧柔,則需要在當(dāng)前對象上生成重量鎖來進行多線程同步漆弄,然后將Tag狀態(tài)改為10,并生成Monitor對象(重量鎖對象)非剃,對象頭里也會放入Monitor對象的地址置逻。最后將當(dāng)前線程t排隊隊列中。

輕量鎖的解鎖過程也很簡單就是把棧幀里剛才的那個lock?record拷貝到對象頭里备绽,若替換成功券坞,則解鎖完成,若替換不成功肺素,表示在當(dāng)前線程持有鎖的這段時間內(nèi)恨锚,其他線程也競爭過鎖,并且發(fā)生了鎖升級為重量鎖倍靡,這時需要去Monitor的等待隊列中喚醒一個線程去重新競爭鎖猴伶。

偏向鎖是比輕量鎖還輕量的鎖機制。當(dāng)synchronized區(qū)域長期都由同一個線程加鎖塌西、解鎖時他挎,jvm就用偏向鎖來做,它的加鎖解鎖比輕量鎖操作起來指令更加簡化捡需。不過一旦有其他線程使用synchronized區(qū)域办桨,即使沒有線程間競爭,也會把偏向鎖升級為輕量鎖站辉,當(dāng)然如果發(fā)生線程競爭就再升級為對象鎖呢撞。

鎖的公平與不公平:公平鎖是指線程獲得鎖的順序按照fifo的原則,先排隊的先得饰剥。非公平鎖指每個線程都先要競爭鎖殊霞,不管排隊先后,所以后到的線程有可能無需進入等待隊列直接競爭到鎖汰蓉。非公平鎖雖然可能導(dǎo)致某些線程饑餓绷蹲,但是鎖的吞吐率是公平鎖好幾倍,synchronized是一個典型的非公平鎖方案顾孽,而且沒法做成公平鎖瘸右。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末娇跟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子太颤,更是在濱河造成了極大的恐慌苞俘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄章,死亡現(xiàn)場離奇詭異吃谣,居然都是意外死亡,警方通過查閱死者的電腦和手機做裙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門岗憋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锚贱,你說我怎么就攤上這事仔戈。” “怎么了拧廊?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵茄袖,是天一觀的道長雇毫。 經(jīng)常有香客問我增炭,道長辣卒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任倦春,我火速辦了婚禮户敬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘睁本。我一直安慰自己尿庐,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布呢堰。 她就那樣靜靜地躺著屁倔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪暮胧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天问麸,我揣著相機與錄音往衷,去河邊找鬼。 笑死严卖,一個胖子當(dāng)著我的面吹牛席舍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哮笆,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼来颤,長吁一口氣:“原來是場噩夢啊……” “哼汰扭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起福铅,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤萝毛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后滑黔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笆包,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年略荡,在試婚紗的時候發(fā)現(xiàn)自己被綠了庵佣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡汛兜,死狀恐怖巴粪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情粥谬,我是刑警寧澤肛根,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站帝嗡,受9級特大地震影響晶通,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哟玷,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一狮辽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巢寡,春花似錦喉脖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谦絮,卻和暖如春题诵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背层皱。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工性锭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叫胖。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓草冈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怎棱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

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