CLR線程概覽(下)

同步: 托管代碼

托管代碼可以訪問很多在System.Threading里定義的同步原語株搔。包括操作系統(tǒng)原語的簡單封裝如:互斥(Mutex)噩翠,事件(Event)和旗標(Semaphore)對象狈涮,也包括類似的柵欄(Barrier)和自旋鎖(SpinLock)等抽象颤介。但托管代碼用的最多的同步機制是System.Threading.Monitor掸犬,其提供了針對 任意托管對象 的高性能同步鎖機制帝雇,還提供了被其保護的狀態(tài)發(fā)生變化時的通知機制的“條件變量”語義聋伦。

Monitor是通過一個“混合鎖”來實現(xiàn)的夫偶,其有自旋鎖和類似互斥(Mutex)這些基于操作系統(tǒng)內(nèi)核鎖的功能界睁。這個思路源自于大部分鎖都是短暫獲取的,因此自旋等待鎖被釋放的所耗費的時間比調(diào)用內(nèi)核API從而阻塞線程更少兵拢。當然將CPU的時鐘周期浪費在自旋上也是很嚴重的翻斟,因此如果鎖在一段時間內(nèi)沒有被釋放的話,那么CLR則會退回到調(diào)用內(nèi)核API的實現(xiàn)上说铃。

因為任意一個對象都是潛在的鎖/條件變量访惜,每個對象都需要有一個地方用來保存鎖信息。這個就是在“對象頭(object headers)”和“同步塊(sync blocks)”里完成的腻扇。

對象頭是一個在每個托管對象前面機器字長大小的字段债热。它在很多地方會用到,例如保存對象的哈希值幼苛。其中一個目的就是保存對象的鎖狀態(tài)窒篱。如果對象頭需要保存更多的信息,我們通過創(chuàng)建一個“同步塊”的方式擴充對象舶沿。

同步塊保存在同步塊表(Sync Block Table)里墙杯,通過同步塊索引來尋址。對象的同步塊索引保存在對象頭里括荡。

關于對象頭和同步塊的細節(jié)在syncblk.h/.cpp里定義霍转。

如果對象頭里還有空間,Monitor將鎖住對象的線程的托管線程ID(如果沒有線程鎖住對象則是0)保存在其中一汽。在這種情形下避消,獲取鎖的過程其實就是自旋等待對象頭的線程ID為0,然后原子操作設置其值為當前線程的托管線程ID召夹。

如果自旋一些次數(shù)后還不能獲取鎖岩喷,或?qū)ο箢^已經(jīng)用作其它目的,那么就會為這個對象創(chuàng)建同步塊监憎。它包含一些額外數(shù)據(jù)纱意,包括用來阻塞當前線程的事件對象,這樣運行我們停止自旋并等待鎖被釋放鲸阔。

一個用來作為條件變量的對象(通過Monitor.Wait 和 Monitor.Pulse)總是會被擴充的偷霉,因為同步塊里已經(jīng)沒有足夠的空間來保存必要的狀態(tài)。

同步: 原生情況

CLR的原生部分也必須要有線程意識褐筛,因為其可能在多個線程上調(diào)用托管代碼类少。這樣要求原生的同步機制,例如鎖渔扎,事件等等硫狞。

ITaskHost API 允許一個CLR宿主修改托管線程的很多方面,包括線程的創(chuàng)建、銷毀和同步残吩。這種允許宿主修改原生同步機制要求虛擬機的代碼不能直接使用原生的同步原語(即臨界區(qū)财忽,互斥鎖,事件等)泣侮,而是需要使用虛擬機在其上的封裝)即彪。

除了上述細節(jié)之外,GC懸停是一個特殊的“鎖”活尊,而且?guī)缀跤绊慍LR的方方面面祖凫。如果必須處理GC堆上的對象,虛擬機的原生代碼可能要進入“合作”模式酬凳,這樣“GC懸停鎖”就變成原生虛擬機代碼里最重要的同步機制惠况,在托管世界里也一樣。

原生虛擬機代碼里主要用到的同步機制是GC模式和Crst宁仔。

GC 模式

如上所述稠屠,所有托管線程都在合作模式中運行,因為其可能操作GC堆翎苫。一般來講权埠,原生代碼不會碰托管對象,因此運行在優(yōu)先模式煎谍。但有些虛擬機里的原生代碼需要訪問GC堆攘蔽,需要運行在合作模式。

原生代碼通常不會直接操作GC模式呐粘,而是通過兩個宏:GCX_COOP and GCX_PREEMP 來進入期望的模式满俗,并創(chuàng)建“支持物”以便線程在退出范圍的時候返回到之前的模式。

需要注意的是GCX_COOP從GC堆上獲取一個鎖作岖。在線程處于合作模式時唆垃,不能執(zhí)行GC。而且原生線程也不能像托管線程那樣被“劫持”痘儡,因此線程在切換回優(yōu)先模式時都是處于合作模式辕万。

因此在原生代碼里進入合作模式是不被鼓勵的。如果必須要進入合作模式沉删,那么時間越短越好渐尿。線程在此模式時不能被阻塞,而且實際上不能安全的獲取鎖矾瑰。

類似的砖茸,GCX_PREEMP 釋放 線程擁有的鎖。在進入優(yōu)先模式之前必須要萬分小心來確保所有GC引用都被妥善保護脯倚。

代碼規(guī)范 文檔描述了安全進行GC模式切換的必要原則渔彰。

Crst

正如Monitor對象是托管代碼里推薦的鎖機制嵌屎,Crst是虛擬機代碼里的推薦機制推正。與Monitor類似恍涂,Crst是一個知道宿主和GC模式的混合鎖。Crst通過“層級鎖”機制來規(guī)避死鎖植榕,該實現(xiàn)可參考 BotR的層級鎖章節(jié).

雖然有一些必須這么做的異常情況再沧,在合作模式下獲取一個Crst鎖通常是不合適的。

特殊線程

除了托管代碼創(chuàng)建的托管線程尊残,CLR自身還創(chuàng)建了一些“特殊”線程炒瘸。

終結(jié)者(Finalizer)線程

每個進程都創(chuàng)建了這個線程用來運行托管代碼。當GC決定一個可終結(jié)(finalizable)的對象不再被引用寝衫,其將該對象置于終結(jié)隊列顷扩。當GC結(jié)束后,終結(jié)者線程會被喚醒并處理隊列里的所有終結(jié)對象慰毅。對象一個一個出列隘截,其終結(jié)(finalizer)函數(shù)被依次調(diào)用。

該線程還用來處理一些CLR內(nèi)部的清理工作汹胃,并等待一些外部事件通知(如低內(nèi)存情形下婶芭,GC會被告知盡量兇悍的回收垃圾)。詳情請參見GCHeap::FinalizerThreadStart着饥。

GC 線程

當運行在“并行”或“服務器”模式時犀农,GC創(chuàng)建一個或多個后臺線程來并行執(zhí)行垃圾回收的不同階段。這些線程完成由GC管理宰掉,而且永遠不會執(zhí)行托管代碼鞭盟。

調(diào)試器線程

CLR為每個托管進程維護了一個原生線程,其用來在附加到托管調(diào)試器時執(zhí)行多個調(diào)試操作局嘁。

應用程序域卸載線程

這個線程負責卸載應用程序域奠衔。其通過一個單獨的CLR內(nèi)部線程,而不是在請求卸載應用程序域的線程里完成戚绕。因為 a) 為卸載過程提供受保證的堆椢谱空間,b) 在必要時允許請求卸載的線程從應用程序域里向上展開舞丛。

線程池線程

CLR線程池維護一個托管線程集合用來執(zhí)行用戶的“工作”耘子。這些托管線程都綁定到線程池管理的原生線程。線程池還維護一小部分的原生線程來處理類似“線程注入”球切,定時器以及“已注冊的等待”等等功能谷誓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吨凑,隨后出現(xiàn)的幾起案子捍歪,更是在濱河造成了極大的恐慌户辱,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糙臼,死亡現(xiàn)場離奇詭異庐镐,居然都是意外死亡,警方通過查閱死者的電腦和手機变逃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門必逆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人揽乱,你說我怎么就攤上這事名眉。” “怎么了凰棉?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵损拢,是天一觀的道長。 經(jīng)常有香客問我撒犀,道長福压,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任绘证,我火速辦了婚禮隧膏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嚷那。我一直安慰自己胞枕,他們只是感情好,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布魏宽。 她就那樣靜靜地躺著腐泻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪队询。 梳的紋絲不亂的頭發(fā)上派桩,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音蚌斩,去河邊找鬼铆惑。 笑死,一個胖子當著我的面吹牛送膳,可吹牛的內(nèi)容都是我干的员魏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼叠聋,長吁一口氣:“原來是場噩夢啊……” “哼撕阎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碌补,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤虏束,失蹤者是張志新(化名)和其女友劉穎棉饶,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镇匀,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡照藻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了坑律。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岩梳。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡囊骤,死狀恐怖晃择,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情也物,我是刑警寧澤宫屠,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站滑蚯,受9級特大地震影響浪蹂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜告材,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一坤次、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧斥赋,春花似錦缰猴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至隘膘,卻和暖如春疑故,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背弯菊。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工纵势, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人管钳。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓钦铁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蹋嵌。 傳聞我的和親對象是個殘疾皇子育瓜,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

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