1、windows爲何要支持線程編程
早期操做系統的情況:早期,操做系統沒有線程的概念。整個系統只運行着一個執行線程,其中同時包含操做系統代碼和應用程序代碼。windows
問題:長時間運行的任務會阻止其餘任務的執行。某個應用程序的執行可能會凍結整個機器,形成OS和其餘應用程序中止響應。若是應用程序有bug,會形成無線循環,一樣會形成整個機器中止工做,而且會致使數據丟失。緩存
改進:構建一個新的OS來知足企業和我的的須要。架構
一、MS在設計這個OS的內核時。決定在一個進程中運行應用程序的每一個實例。進程是應用程序的一個實例要使用的資源的一個集合。每一個進程都被賦予了一個虛擬的地址空間,確保一個進程使用的代碼和數據沒法由另外一個進程訪問。這就確保了應用程序實例的健壯性,由於一個進程沒法破壞另外一個進程使用的代碼和數據。除此以外,OS的內核代碼和數據是進程訪問不到的,因此應用程序破壞不了操做系統的代碼和數據。編程語言
二、可是CPU自己呢?若是一個應用程序進入無限循環,而且機器中只有一個CPU,那他會執行無限循環,不能執行其餘任何東西。因此,系統仍是可能會中止響應。MS對於這個問題拿出的解決方案是線程。線程的職責是對CPU進行虛擬化。Windows爲每一個進程都提供了該進程專用的線程(功能至關於一個CPU,可將線程理解爲一個邏輯CPU)。若是應用程序的代碼進入無線循環,與那個代碼關聯的進程會「凍結」,但其餘的進程還會繼續執行。函數
2、線程開銷性能
和一切虛擬化機制同樣,線程會產生空間(內存耗用)和時間(運行時的執行性能)上的開銷。spa
每一個線程中,都有如下要素:操作系統
一、線程內核對象。線程
二、線程環境塊。
三、用戶模式棧。
四、內核模式棧。
五、DLL線程連接和線程分離通知。
建立和終止線程引發的開銷:任什麼時候候在進程中建立一個線程,都會調用那個進程中加載的全部DLL的DllMain方法,並向該方法傳遞一個DLL_THREAD_ATTACH標識。相似的,任什麼時候候一個線程終止,都會調用進程中的全部DLL的DllMain方法,並向該方法傳遞一個DLL_THREAD_DETACH標識。(注:C#和其餘大多數的編程語言生產的DLL沒有DLLMain函數,因此託管DLL不會收到DLL_THREAD_ATTACH和DLL_THREAD_DETACH的通知,這提高了性能。)
上下文切換引發的開銷:單CPU的計算機一次只能作一件事情。因此Windows必須在系統中的全部線程(邏輯CPU)之間共享物理CPU。在任何給定的時刻,Windows只將一個線程分配給一個CPU,那個線程容許運行一個「時間片」,一旦時間片到期,Windows就上下文切換到另外一個線程,每次上下文切換都要求Windows執行如下操做:
一、將CPU寄存器中的值保存到當前正在運行的線程的內核對象內部的一個上下文結構中。
二、從現有的線程集合中選出一個線程供調度。若是該線程有由另外一個進程擁有,Windows在開始執行任何代碼或者接觸任何數據以前,還必須切換CPU「看見」的虛擬地址空間。
三、將所選上下文結構中的值加載到CPU的寄存器中。
Windows大約每30毫秒執行一次上下文切換。上下文切換是淨開銷:也就是說上下文切換所產生的開銷不會換來任何內存或者性能上的收益。Windows執行上下文切換,向用戶提供一個健壯的、響應靈敏的操做系統。執行上下文切換所須要的時間取決於CPU架構和速度。而填充CPU緩存所需時間取決於系統中運行的應用程序、CPU緩存的大小及其餘各類因素。因此沒法爲每一次上下文切換的時間開銷給出一個肯定的值,甚至沒法給出一個估計的值。惟一肯定的是,若是要構建高性能的應用程序和組件,就應該儘量的避免上下文切換。
在執行垃圾回收時,CLR必須掛起(暫停)全部線程,遍歷他們的棧來查找跟以便對對堆中的對象進行標記,再次遍歷他們的棧(對象在壓縮期間可能發生了移動,因此要更新他們的根),再恢復全部線程。因此,減小線程的數量會限制提高垃圾回收器的性能。
未完待續.........