主頁 > 知識(shí)庫 > .NET 線程基礎(chǔ)的使用介紹

.NET 線程基礎(chǔ)的使用介紹

熱門標(biāo)簽:五常地圖標(biāo)注 鄭州400電話辦理 聯(lián)通 戶外地圖標(biāo)注軟件手機(jī)哪個(gè)好用 凱立德導(dǎo)航官網(wǎng)地圖標(biāo)注 智能電話營銷外呼系統(tǒng) 電銷語音自動(dòng)機(jī)器人 地圖標(biāo)注和認(rèn)領(lǐng) 萊蕪?fù)夂綦婁N機(jī)器人價(jià)格 長春呼叫中心外呼系統(tǒng)哪家好

線程作用及開銷

  早期計(jì)算機(jī)一次只能運(yùn)行一個(gè)程序,長時(shí)間執(zhí)行程序容易出現(xiàn)計(jì)算機(jī)“癱瘓”的問題,如果程序進(jìn)入死循環(huán)則只能重啟系統(tǒng)。即使計(jì)算機(jī)不崩潰,也難免讓用戶崩潰。為了解決這個(gè)問題,操作系統(tǒng)設(shè)計(jì)者設(shè)計(jì)出了進(jìn)程的概念,使得每個(gè)應(yīng)用程序運(yùn)行在一個(gè)虛擬的內(nèi)存空間中。進(jìn)程中又包含多個(gè)線程,CPU則根據(jù)操作系統(tǒng)調(diào)度執(zhí)行每個(gè)進(jìn)程中的線程任務(wù)。通過線程這種對CPU的虛擬化管理方式,操作系統(tǒng)形成了多任務(wù)執(zhí)行的機(jī)制。但與一切虛擬化機(jī)制一樣,線程會(huì)產(chǎn)生空間和時(shí)間的開銷。這其中的開銷包括:

1、線程內(nèi)核對象。該數(shù)據(jù)結(jié)構(gòu)中包含線程上下文。Windows在x86架構(gòu)CPU上為每個(gè)線程內(nèi)核對象分配的空間大約為700字節(jié),x64和IA64架構(gòu)CPU分別為大約1240字節(jié)和2500字節(jié)。

2、線程環(huán)境塊。占用一個(gè)內(nèi)存頁,包含線程的異常處理鏈?zhǔn)?。?dāng)線程進(jìn)入try塊時(shí),在鏈?zhǔn)撞迦胍粋€(gè)節(jié)點(diǎn),在線程對出退出try塊時(shí),刪除該節(jié)點(diǎn)。另外線程環(huán)境塊中還包括一些其他的本地儲(chǔ)蓄數(shù)據(jù)。

3、用戶模式棧。用戶存儲(chǔ)傳給方法的局部變量和實(shí)參;還包含一個(gè)地址,指出當(dāng)方法返回時(shí),線程應(yīng)該從什么地方開始接著執(zhí)行。默認(rèn)情況下每個(gè)線程的用戶模式棧分配1MB內(nèi)存。

4、內(nèi)核模式棧。記錄用戶程序調(diào)用內(nèi)核模式函數(shù)時(shí)函數(shù)的實(shí)參。32位系統(tǒng)分配12KB內(nèi)存,64位系統(tǒng)則分配24KB。

5、DLL線程連接和線程分離通知。進(jìn)程中每創(chuàng)建和終止一個(gè)線程時(shí),都會(huì)調(diào)用進(jìn)程中加載的所有DLL的DllMain方法。

6、上下文切換。對單CPU計(jì)算機(jī)來說,操作系統(tǒng)每次只將一個(gè)線程分配給CPU執(zhí)行,執(zhí)行完后將線程上下文數(shù)據(jù)記錄下來保存在線程內(nèi)核對象結(jié)構(gòu)中;然后裝載另一個(gè)線程的上下文,將CPU執(zhí)行控制交給此線程,如果該線程有另一個(gè)進(jìn)程擁有,那么在裝載該線程之前,Windows還必須使得CPU能夠處理該虛擬地址空間。Windows操作系統(tǒng)為各個(gè)線程每次分配大概30毫秒的執(zhí)行時(shí)間,稱為“時(shí)間片”。上下文切換是凈開銷,不會(huì)換來任何在存儲(chǔ)空間或者性能上的收益。但是能向用戶提供一個(gè)健壯的能靈活相應(yīng)的操作系統(tǒng)。

空間開銷測試

測試代碼:

復(fù)制代碼 代碼如下:

static void Main(string[] args)
         {
             ListThread> threadList = new ListThread>();
             for (int i = 0; i 1000; i++)
             {
                 Thread thread = new Thread(
                     new ParameterizedThreadStart(o => { Console.WriteLine("第{0}線程", o); Thread.Sleep(100000); })
                     );
                 threadList.Add(thread);
             }
             Console.ReadLine();
             for (int i = 0; i threadList.Count; i++)
             {
                 threadList[i].Start(i);
             }
             Console.ReadLine();
         }

pslist的觀測結(jié)果結(jié)果:

程序開始運(yùn)行時(shí)

所有線程Start以后

1000個(gè)線程Start以后虛擬物理內(nèi)存占用量增加了31MB,而虛擬內(nèi)存增加了1000MB之多。

線程池

  由于專用線程(實(shí)例化Thread類所創(chuàng)建的線程)存在的巨大內(nèi)存和性能開銷,CRL被設(shè)計(jì)出支持線程池技術(shù),為應(yīng)用程序提供線程管理。每個(gè)CLR獨(dú)立維護(hù)一個(gè)自己的線程池,CLR在線程池中只建立必要的線程供給應(yīng)用程序使用,在應(yīng)用程序把多個(gè)任務(wù)分配給線程池后,CLR將任務(wù)輪流分配給線程池中線程來執(zhí)行,當(dāng)任務(wù)執(zhí)行完畢后,線程池中的線程并不會(huì)回收,而是等待分配新的任務(wù)。這就能有效的減少線程的數(shù)量,并且減少了線程創(chuàng)建時(shí)的性能開銷(線程池相關(guān)的內(nèi)容筆者正在整理之中,后續(xù)會(huì)陸續(xù)發(fā)布)。另外,對于Thread類有一個(gè)實(shí)例屬性IsBackground指示線程是前臺(tái)還是后臺(tái)運(yùn)行,前臺(tái)線程指線程所在進(jìn)程關(guān)閉時(shí),進(jìn)程需要等待線程執(zhí)行完成才能關(guān)閉,后臺(tái)進(jìn)程指當(dāng)進(jìn)程關(guān)閉時(shí),線程立即停止執(zhí)行,不會(huì)等待執(zhí)行完成既退出運(yùn)行。該屬性默認(rèn)值為True,即專用線程默認(rèn)為前臺(tái)線程。

進(jìn)程、AppDomain和線程

  這里涉及到進(jìn)程,AppDomain和線程,我覺得有必要把這三個(gè)概念放一起做一個(gè)大體的比對。

  1、進(jìn)程是操作系統(tǒng)為應(yīng)用程序虛擬的執(zhí)行地址空間,應(yīng)用程序中的所有數(shù)據(jù)都裝載在相互獨(dú)立的進(jìn)程中運(yùn)行。

  2、AppDomain是.NET托管應(yīng)用裝載的內(nèi)部相互隔離的托管執(zhí)行空間。如:IIS進(jìn)程中所有的Web應(yīng)用都運(yùn)行在獨(dú)立的AppDomain中。

  3、線程是應(yīng)用程序內(nèi)部虛擬化的CPU執(zhí)行單元,操作系統(tǒng)對內(nèi)存中所有應(yīng)用程序進(jìn)程中的線程進(jìn)行調(diào)度,交給CPU進(jìn)行執(zhí)行。

  進(jìn)程是一個(gè)虛擬的地址空間,操作系統(tǒng)不會(huì)對其進(jìn)行調(diào)度而是調(diào)度執(zhí)行其中包含的線程。CLR在AppDomain內(nèi)部也有自己的運(yùn)行線程,AppDomain中的線程由CLR維護(hù),但最終CLR仍需將AppDomain中的線程映射為應(yīng)用程序進(jìn)程中的線程,交給操作系統(tǒng)進(jìn)行調(diào)度。并且AppDomain中的線程不一定與操作系統(tǒng)線程完全一一對應(yīng)。

  下圖是大體描述進(jìn)程、AppDomain和線程的關(guān)系,以及操作系統(tǒng)對線程的調(diào)度。詳細(xì)內(nèi)容本文不做進(jìn)一步說明。

線程優(yōu)先級(jí)

  線程調(diào)度根據(jù)線程優(yōu)先級(jí)進(jìn)行,Windows將系統(tǒng)內(nèi)的線程分為0至31,共32個(gè)等級(jí),優(yōu)先級(jí)為31的線程是最高優(yōu)先級(jí)線程,最先得到執(zhí)行權(quán)限。例如,一個(gè)優(yōu)先級(jí)為8的線程正在執(zhí)行,而此刻操作系統(tǒng)確認(rèn)一個(gè)優(yōu)先級(jí)為31的線程已經(jīng)做好了執(zhí)行準(zhǔn)備,那么操作系統(tǒng)會(huì)立刻掛起正在執(zhí)行的線程,把CPU的執(zhí)行權(quán)限交給優(yōu)先級(jí)為31的線程,即使優(yōu)先級(jí)為8的線程還沒有執(zhí)行完一個(gè)完整的時(shí)間片,優(yōu)先級(jí)為31的線程將獲得一個(gè)完整的時(shí)間片,如果該線程執(zhí)行完后操作系統(tǒng)發(fā)現(xiàn)還有優(yōu)先級(jí)為31的線程準(zhǔn)備執(zhí)行,那么CPU執(zhí)行權(quán)限將分給這個(gè)線程,前面優(yōu)先級(jí)為8的線程始終得不到執(zhí)行,這種情況稱為饑餓。

  ​​如果開發(fā)人員沒有合理的設(shè)置自己程序內(nèi)的線程優(yōu)先級(jí),就可能會(huì)造成其他應(yīng)用程序很難得到執(zhí)行,甚至影響計(jì)算機(jī)響應(yīng)速度。所以Windows又設(shè)計(jì)了一個(gè)進(jìn)程優(yōu)先級(jí)類來控制各個(gè)進(jìn)程中的線程優(yōu)先級(jí)的關(guān)系,進(jìn)程優(yōu)先級(jí)是一個(gè)虛擬的概念,因?yàn)椴僮飨到y(tǒng)不會(huì)對進(jìn)程進(jìn)行調(diào)度,這個(gè)概念只是為了控制進(jìn)程中線程優(yōu)先級(jí)的范圍。進(jìn)程優(yōu)先級(jí)有6個(gè)級(jí)別(詳見下表),根據(jù)進(jìn)程優(yōu)先級(jí)類,應(yīng)用程序?qū)?nèi)部線程設(shè)置相對優(yōu)先級(jí),會(huì)得到一個(gè)操作系統(tǒng)調(diào)度的線程優(yōu)先級(jí)值。這樣,使線程優(yōu)先級(jí)能得到有效控制。

線程相對

優(yōu)先級(jí)

進(jìn)程優(yōu)先級(jí)類

Idle

Below Normal

Normal

Above Normal

High

Real-Time

Time-critical

15

15

15

15

15

31

Highest

6

8

10

12

15

26

Above normal

5

7

9

11

14

25

Normal

4

6

8

10

13

24

Below normal

3

5

7

9

12

23

Lowest

2

4

6

8

11

22

Idle

1

1

1

1

1

16

標(biāo)簽:紅河 岳陽 西藏 西寧 衢州 湖州 宣城 福州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《.NET 線程基礎(chǔ)的使用介紹》,本文關(guān)鍵詞  .NET,線程,基礎(chǔ),的,使用,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《.NET 線程基礎(chǔ)的使用介紹》相關(guān)的同類信息!
  • 本頁收集關(guān)于.NET 線程基礎(chǔ)的使用介紹的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章