作業系統建立執行緒是有代價的,其主要開銷在下面列舉出來了。
執行緒核心物件
擁有執行緒描述屬性與執行緒上下文,執行緒上下文占用的記憶體空間為 x86 架構 占用 700 位元組、x64 架構 1240 位元組 、arm 架構 350 位元組。
執行緒環境塊(teb)
teb 消耗乙個記憶體頁,占用 4kb記憶體。
使用者模式棧。
使用者模式棧儲存傳遞給方法的區域性變數與實參,並且還儲存有乙個位址用於當前方法返回的時候,執行緒應該從哪個地方繼續執行。預設 windows 分配保留 1mb 記憶體。
核心模式棧。
32 位 windows 占用 12 kb,64 位 windows 占用 24 kb。
dll 執行緒連線與執行緒分離通知。
這種策略只有 windows 才會存在,當建立執行緒時, windows 會呼叫程序所有非託管 dll 的 dllmain 方法,並未其傳遞 dll_thread_attach 標誌,執行緒終止時傳遞 dll_thread_detach 標誌。
windows 在任何時刻都只會將 1 個執行緒分配給 1 個 cpu ,該執行緒享有乙個時間片的執行時間。時間片到期之後,windows 會將上下文切換到另外乙個執行緒,動作如下:
將 cpu 暫存器值儲存在當前正在執行的執行緒的核心物件內部的上下文結構之中。
從先有執行緒集合選取乙個執行緒供排程,如果該執行緒屬於另乙個程序,還得切換 cpu 能夠操作的虛擬位址空間。
將上下文結構中的值載入到 cpu 暫存器之中。
以上操作做完之後,windows 等待這個執行緒時間片到期,執行下次切換,每次切換的時間開銷大概為 30 毫秒。
如果乙個執行緒時間片結束之後,下乙個排程的執行緒還是之前的執行緒則不會產生執行緒上下文切換。
所以在理想狀態下,每個系統最佳的執行緒數應該與其核心數相同,(如果是 4 核 8 執行緒則最優應該為 8 個)因為這樣上下文切換出現的情況就會少很多。
最重要的是,windows 系統上大部分程式執行緒都處於空閒狀態,但是執行緒占用的記憶體空間是事實存在的。
一般來說不推薦使用 thread 手動建立執行緒,而應該使用執行緒池,不過在有以下需求時,可以手動建立執行緒。
需要設定更高的執行緒優先順序的時候。
需要將執行緒設定為前台執行緒。
某些長耗時的專用線程。
該執行緒可能會通過 thread 的 abort 方法終止自身。
在呼叫過程中,如果使用了thread.join()
方法那麼就會造成呼叫執行緒阻塞當前**,直到建立的執行緒被終止。
針對於客戶端程式而言,多執行緒可以增強響應性,不會因為耗時操作阻塞 ui 執行緒造成使用者體驗卡頓。
針對於伺服器程式而言,可以併發地處理使用者請求,充分利用多核 cpu 的優勢。
作者的觀點是,計算機的 cpu 使用率應該保持 100% 的使用率才不算是浪費計算資源。
搶占式系統通過優先順序來判定執行緒在什麼時候排程多少時間,每個執行緒都分配了從 0 到 31 的優先順序,系統為 cpu 分配執行緒時,首先檢查 31 的執行緒,並以輪詢的方式排程他們(優先順序都為 31)。
如果高優先順序的執行緒一直處於排程狀態,那麼作業系統不會將 cpu 分配給低優先順序的執行緒,這樣就會造成執行緒飢餓。
較高的優先順序執行緒總會搶占低優先順序執行緒,即便該執行緒的時間片沒有用完。
cpu 會建立乙個優先順序為 0 的零頁執行緒,該執行緒是系統唯一乙個優先順序為 0 的執行緒,只有在 cpu 空閒的時候會執行他,用於清理 ram 中所有的空閒記憶體頁。
【注意】windows 通過兩個抽象層用於表示程序優先順序類和執行緒優先順序,單一般 c# 使用者**中能夠控制的只有執行緒優先順序,他們分別是:lowest、belownormal、normal、abovenormal、highest。程序優先順序類 + 執行緒優先順序構成了乙個基礎優先順序,windows 還有乙個動態優先順序用於防止產生執行緒飢餓,會動態調成執行緒的優先順序狀態。
但是動態優先順序只會針對基礎優先順序在 0 ~ 15 的執行緒應用,16 ~ 31 不受這個管控。
在 clr 中線程只有兩種狀態,前台執行緒和後台執行緒,而且當所有前台執行緒被終止之後,clr 會強行關閉所有後台執行緒,並退出程式。
執行緒在執行的生命週期當中可以變更其狀態,但主線程預設為前台執行緒,使用 thread 型別建立的執行緒預設也是前台執行緒。只有執行緒池的執行緒預設為後台執行緒,進入託管執行的本機**建立的任何執行緒也會標記為後台執行緒。
CLR via C 讀書筆記1 9
與非託管 的互操作 clr 提供3種與非託管 的互動方案 託管 通過使用 p invoke 機制 來呼叫dll檔案中的非託管函式 許多 fcl 中定義的型別內部都有呼叫到 kernel32.dll,user32.dll 等等檔案中的函式。同時許多程式語言會提供託管 呼叫非託管 的簡便途徑,比如 c ...
CLR via C 讀書筆記2 2
把型別編譯成乙個模組 先假設有這麼乙個簡單的程式 public sealed class program 該程式定義乙個名為 program 的型別,它擁有乙個公有靜態 public,static 方法 main,該方法參照 system.console。把源 存為 program.cs 執行以下命...
CLR via C 讀書筆記目錄
一口氣寫了clr via c 兩章的筆記,有些內容自己也似懂非懂,有些則覺得很好很強大,所以趁此機會作個目錄同時為每篇文章打個評分 clr via c 讀書筆記1 1 託管模組 managed modules 定義 clr via c 讀書筆記1 2 程式集 assemblies 定義 clr vi...