1.1、執行緒職責
執行緒的職責是對cpu
進行虛擬化。windows 為每個程序豆提供了該程序專用的執行緒(功能相當於乙個cpu)。應用程式的**進入死迴圈,於那個**關聯的程序會「凍結」,但其他程序不會凍結,它們會繼續執行!
1.2、執行緒開銷
和一切虛擬化機制一樣,執行緒有空間(記憶體耗用)和時間(執行時的執行效能)上的開銷。
每個執行緒都有以下要素。
windows 任何時刻只將乙個執行緒分配給乙個cpu。那個執行緒只能執行乙個「時間片」(有時也稱為「量」或者「量程」,即 quantum)的長度。時間片到期,windows 就上下文切換到另乙個執行緒。每次上下文切換都要求windows 執行以下操作:
將cpu暫存器的值儲存到當前正在執行的執行緒的核心物件內部的乙個上下文結構中。
從現有執行緒集合中選出乙個執行緒供排程。如果該執行緒由另乙個程序擁有,windows 在開始執行任何**或者接觸任何資料之前,還必須切換cpu「看見」的虛擬位址空間。
將所選上下文結構中的值載入到cpu暫存器中。
上下文切換完成後,cpu會執行選擇的執行緒直到它的時間片結束。然後另乙個上下文切換發生。windows大概每30ms
執行一次上下文切換。上下文切換是淨開銷
;也就是說,上下文切換所產生的開銷不會換來任何記憶體或是效能上的收益。windows執行上下文切換,向使用者提供乙個健壯、響應靈敏的作業系統。
現在,如果乙個應用程式的執行緒進入無限迴圈,windows會定期搶占(preempt)它,將乙個不同的執行緒分配給乙個實際的cpu,然後讓這個新執行緒執行一會。假定新執行緒是任務管理器裡的執行緒,現在終端使用者就可以利用任務管理器來結束這個包含了無限迴圈執行緒的程序。之後,程序會終止,它處理的所有資料也會被銷毀。但是,系統中的其他所有程序都繼續執行,不會跌勢它們的資料。當然,使用者也不用重啟。所以上下文切換通過犧牲效能來換取更好的使用者體驗。
實際上,效能上的損耗比你想想中的還要厲害。是的,當windows上下文切換到另乙個執行緒的時候,會發生一定的效能損失。但是,cpu現在是要執行乙個不同的執行緒,而之前的執行緒的**和資料還在cpu的告訴快取(cache)中,這使得cpu不必經常訪問ram(他的速度比cpu告訴快取慢得多)。當windows上下文切換到乙個新執行緒時,這個新線程極有可能要執行不同的**並訪問不同的資料,這些**和資料不在cpu的告訴快取中。因此,cpu必須訪問ram來填充它的告訴快取,以回覆高速執行狀態。但是,在30ms後,一次新的上下文切換又發生了。
執行上下文切換的時間取決於不同的cpu架構和速度。而填充cpu快取所需的時間取決於系統中執行的應用程式、cpu快取的大小以及其他各種因素。所以,我不可能給你乙個關於上下文切換時間的確切值,甚至是估計值。唯一確定的是,如果要構建高效能的應用程式和元件,就應該盡可能的避免上下文切換。
!!!:
在乙個時間片結束的時候,如果windows決定再次排程同乙個執行緒(而不是切換到另乙個執行緒),那麼windows不會執行上下文切換。相反,執行緒將繼續執行。這顯著的改進了效能。設計自己的**的時候,注意能避免上下文切換的就避免。
!!!:
乙個執行緒可以自動的提前結束它的時間片。這是經常發生的,因為執行緒經常要等待i/o操作(鍵盤,滑鼠,檔案,網路等等)來完成。比如,「記事本」程式的執行緒經常處於重現狀態,什麼事情都不做:這個執行緒是在等待輸入。如果使用者按鍵盤上的j鍵,windows會喚醒「記事本」執行緒,讓它處理按鍵操作。「記事本」執行緒可能花費5ms來處理按鍵,然後呼叫乙個win32函式,告訴windows它準備好處理下乙個輸入事件。如果沒有更多的輸入事件,windows會讓「記事本」執行緒進入等待狀態(時間片剩餘的部分就放棄了),使執行緒在任何cpu上都不再排程,知道發生下一次輸入事件。這增強了系統的總體效能,因為正在等待i/o操作的完成的執行緒不會在cpu上排程,所以不會浪費cpu時間;節省出來的時間可供在cpu上排程其他執行緒。
另外,執行gc的時候,clr必須掛起所有的執行緒,遍歷它們的棧來查詢根以便對堆中的物件進行標記,再次遍歷它們的棧(有的物件在壓縮期間發生了移動,所以要更新它們的根),再恢復所有的執行緒。所以,減少執行緒的數量也會顯著提公升gc的效能。每次使用偵錯程式並除錯到乙個斷點,windows都會掛起正在除錯的應用程式中的所有執行緒,並在但不執行或者執行應用程式時恢復所有執行緒。因此,你用的執行緒越多,除錯體驗也就越差。
《CLR Via C 》讀書筆記 26 執行緒基礎
作業系統建立執行緒是有代價的,其主要開銷在下面列舉出來了。執行緒核心物件 擁有執行緒描述屬性與執行緒上下文,執行緒上下文占用的記憶體空間為 x86 架構 占用 700 位元組 x64 架構 1240 位元組 arm 架構 350 位元組。執行緒環境塊 teb teb 消耗乙個記憶體頁,占用 4kb記...
型別基礎 CLR Via C 筆記一
一.所有型別都是從system.obejct派生 1.下面兩個型別定義是完全一致的 1 class employee 4class employee system.object 2.system.object的公共例項方法 a.equals 判斷物件是否具有相等的值 b.gethashcode 返回...
CLR via C 第4章 型別基礎
1.clr最重要的特性之一就是型別安全 在執行時,clr總是知道物件的型別是什麼,呼叫gettype 方法即可知道物件的確切型別。這也就是為什麼gettype 方法是基類object中的非虛方法,因為如果可以重寫gettype 方法,那麼他返回的就不一定是當前的物件型別,違背了型別安全。2.使用 i...