CLR via C# 讀書筆記-26.線程基礎

来源:http://www.cnblogs.com/jdzhang/archive/2017/12/01/7913238.html
-Advertisement-
Play Games

前言 這倆個月沒怎麼寫文章做記錄分享,一直在忙項目上線的事情,但是學習這件事情,停下來就感覺難受,clr線程這章也是反覆看了好多遍,書讀百遍其義自見,今天我們來聊下線程基礎 1.進程是什麼,以及線程起源 2.線程開銷,以及上線文切換 3.使用線程的理由 4.線程調度和優先順序 5.前臺線程和後臺線程 ...


前言

這倆個月沒怎麼寫文章做記錄分享,一直在忙項目上線的事情,但是學習這件事情,停下來就感覺難受,clr線程這章也是反覆看了好多遍,書讀百遍其義自見,今天我們來聊下線程基礎

1.進程是什麼,以及線程起源

2.線程開銷,以及上線文切換

3.使用線程的理由

4.線程調度和優先順序

5.前臺線程和後臺線程

一、進程是什麼,以及線程起源

在電腦的早期歲月,os沒有線程的概念,整個系統只運行者一個執行線程,其中包含操作系統和應用程式的代碼。這意味著長時間運行的任務會阻止其他任務的運行。在16位windows的那些日子,列印文檔的應用程式很容易“凍結”整個機器,造成os和其他應用程式停止響應。遇到這個問題,用戶只能按Reset建或重啟電腦,所有正在運行的應用程式都會終止,造成應用程式正在處理的數據都會無端的丟失,用戶對此深惡痛絕。

Microsoft由此設計出新的OS內核,決定在一個進程中運行應用程式的每個實例,進程實際是 應用程式的實例要使用的資源的集合。每個進程都賦予了一個虛擬的地址空間,確保在一個進程中使用的代碼和數據無法由另一個進程訪問,進程也訪問不了OS的內核代碼和數據,所以,應用程式破壞不了其他應用程式或者OS自身,用戶體驗變得更好了。

聽起來不錯,但CPU本身呢?應用程式發生死迴圈會發生什麼?如果機器只有一個CPU,它會執行死迴圈,雖然數據無法被破壞,但系統仍然可能停止響應。Microsoft拿出的解決方案就是線程。作為一個Windows概念,線程的職責是對CPU進行虛擬化。Windows為每個進程都提供了該進程專用的線程(功能相當於一個CPU)。應用程式的代碼進入死迴圈,與那個代碼關聯的進程會“凍結”,但其他進程(他們有自己的線程)不會凍結,他們會繼續執行!

二、線程開銷

1.線程內核對象(thread kernel object)

OS為系統中創建的每個線程都分配並初始化這種數據結構之一。數據結構包含一組對線程進行描述的屬性。線程結構還包含所謂的線程上下文(thread context)。上下文是包含CPU寄存器集合的記憶體塊。對於x86,x64和ARM CPU架構,線程上下文分別使用約700,1240和350位元組的記憶體

2.線程環境快(thread environment block,TEB)

TEB是在用戶模式(應用程式代碼能快速訪問的地址空間)中分配和初始化的記憶體塊。TEB耗用一個記憶體頁(x86,x64,和ARM CPU中是4KB)。TEB包含線程的異常處理鏈首(head)。線程進入的每個try塊都在鏈首插入一個節點(node);線程退出try塊時從鏈中刪除該節點。此外,TEB還包含線程的“線程本地存儲”數據,以及GDI(Graphics Device Interface,圖形設備介面)和OpenGL圖形使用的一些數據結構

3.用戶模式棧(user-mode stack)

用戶模式棧存儲傳給方法的局部變數和實參。它還包含一個地址;指出當前方法返回時,線程應該從什麼地方接著執行。Windows預設為每個線程的用戶模式棧分配1MB記憶體。

4.內核模式棧(kernel-mode-stack)

應用程式代碼向操作系統中的內核模式函數傳遞實參時,還會使用內核模式棧。由於對安全的考慮,針對從用戶模式的代碼傳給內核的任何實參,Windows都會把它們從線程的用戶模式棧複製到線程的內核模式棧。一經複製,內核就可驗證實參的值。由於應用程式代碼不能訪問內核模式棧,所以應用程式無法更改驗證後的實參值。OS內核代碼開始處理複製的值。除此之外,內核會調用它自己內部的方法,並利用內核模式棧傳遞它自己的實參、存儲函數的局部變數以及存儲返回地址。

4.DLL線程連接(attach)和線程分離(detach)通知

Windows的一個策略是,任何時候在進程中創建線程,都會調用進程中載入的所有非托管DLL的DllMain方法,並向該方法傳遞DLL_THREAD_ATTACH標誌。類似地,任何時候線程終止,都會調用進程中的所有非托管DLL的DllMain方法,並向方法傳遞DLL_THREAD_DETACH標誌。有的DLL需要獲取這些通知,才能為進程中創建/銷毀的每個線程執行特殊的初始化或(資源)清理操作。

也就是說線程創建銷毀時會調用所有DLL中的這個函數,嚴重影響了進程中創建和銷毀線程的性能

上下文切換

單CPU電腦一次只能做一件事情。Windows必須在系統中的所有線程(邏輯CPU)之間共用物理CPU。

Windows任何時刻只將一個線程分配給一個CPU 。那個線程能運行一個“時間片”(有時也成為“量”或者“量程”,即quantum)的長度。時間片到期,Windows就上下文切換到另一個線程。每次上下文切換都要求windows執行以下操作。

1.將CPU寄存器的值保存到當前正在運行的線程的內核對象內部的一個上下文結構中。

2.從現有線程集合中選出一個線程供調度。

3.將所選上下文結構中的值載入到CPU的寄存器中。

上下文切換完成後,CPU執行所選的線程,直到它的時間片到期。然後發生下次上下文切換。Windows大約每30毫秒執行一次上下文切換。

 

要構建高性能應用程式和組件,就應該儘量避免上下文切換。

減少線程的數量也會顯著提升垃圾回收的性能。

三、使用線程的理由

1.可響應性(通常是對於客戶端GUI應用程式)

例如windows中每個進程提供它自己的線程,確保發生死迴圈的應用程式不會妨礙其它應用程式。類似地,在客戶端GUI應用程式中,可以將一些工作交給一些線程進行,使GUI線程能靈敏的響應用戶輸入。

2.性能(對於客戶端和服務端應用程式)

由於windows每個CPU調度一個線程,而且多個CPU能併發執行這些線程,所以同時執行多個操作能提升性能。

滿足以下任何條件,就可考慮顯式創建自己的線程

1.線程需要以非普通線程優先順序運行

2.需要線程表現為一個前臺線程,防止應用程式線上程結束任務前終止

3.計算限制的任務需要長時間運行

4.要啟動的線程,並可能調用Thread的abort方法來提前終止它

四、線程調度和優先順序

每個線程都分配了從0(最低)到31(最高)的優先順序。

只要存在可調度的優先順序31的線程,系統就永遠不會將優先順序0~30的任何線程分配給CPU。這種情況成為饑餓。

系統啟動時會創建一個特殊的零頁線程(zero page thread)。該線程的優先順序為0,而且是整個系統唯一優先順序為0的線程。在沒有其他線程需要“幹活兒”的時候,零頁線程將系統RAM的所有空閑頁清零。

五、前臺線程和後臺線程

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            //創建新線程(預設為前臺線程)
            Thread t = new Thread(Worker);
            //使線程成為後臺線程
            t.IsBackground = true;
            //啟動線程
            t.Start();
            //如果t是前臺線程,則應用程式大概10秒後才終止
            //如果t是後臺線程,則應用程式立即終止
            Console.WriteLine("Returing from Main");
        }

        private static void Worker()
        {
            //模擬做10秒鐘的工作
            Thread.Sleep(10000);
            //下麵這行代碼只有由一個前臺線程執行時才會顯示
            Console.WriteLine("Returning from Worker");
        }
    }
}
View Code

應用程式的主線程以及通過構造一個Thread對象來顯式創建的任何線程都預設為前臺線程。相反,線程池線程預設為後臺線程。

另外,由進入托管執行環境的本機(native)代碼創建的任何線程都被標記為後臺線程。

 

天道酬勤,大道至簡,堅持。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 環境:aix 7.1 ,oracle 12.1.0.2 rac -3節點。 硬體故障後,硬體工程師更換了內聯網卡,不知為何資源VIP也有問題,只好先添加了VIP srvctl add vip -node rac-wy1 -address rac-wy1-vip.nsn.com/255.255.255 ...
  • oracle提供了三個隔離級別: 1.讀提交 ,簡而言之只能讀取語句開始執行前提交的數據 2.串列,這個好理解,就是事務串列運行,避免經典的三個場景-臟讀、不可重覆讀、幻讀。 3.只讀,oracle已經實現的只讀模式。 -- 這些都很容易理解,問題的關鍵是解決一些實際的問題,例如典型的汽車票銷售。 ...
  • 一、建表 1、最簡單的建表CREATE TABLE user(id int,name char(20),age int); 2、帶主鍵帶註釋和預設值創建表CREATE TABLE user(id INT PRIMARY KEY AUTO_INCREMENT COMMENT '設置主鍵自增',name ...
  • 1、表的基本概念 每一行代表一條唯一的記錄,每一列代表記錄中的一個欄位。 2、創建表 例子: 3、查看表結構 (1)DESCRIBE語句查看表定義 語法: 例子: (2)SHOW CREATE TABLE語句查看詳細表詳細定義 語法: 例子: 註意:在顯示表詳細定義信息時,可以使用“;”、“\g”和 ...
  • 1 //首先要添加 System.ServiceProcess.dll 引用 2 ServiceController sc = new ServiceController("MSSQLSERVER"); 3 4 //判斷服務是否已經關閉 5 if (sc.Status == ServiceContr ...
  • ThoughtWorks在每年都會出品兩期技術雷達,這是一份關於技術趨勢的報告,它比起一些我們能在市面上見到的其他各種技術行情和預測報告,更加具體,更具可操作性,因為它不僅涉及到新技術大趨勢,比如雲平臺和大數據,更有細緻到類庫和工具的推介和評論,從而更容易落地。 Thoughtworks技術雷達 T ...
  • Nginx集群是.NET WebApi提供了負載均衡的其中一種實現方式,同時還增加了SSL認證,能夠確保WebApi能夠以加密形式進行響應。Nginx使用其中的SSL模塊,能夠支持HTTPS的配置,當然也能夠讓HTTP與HTTPS並存(只需要增加listen 80監聽埠則可),本文主要實現HTTP... ...
  • 返回總目錄 本小節目錄 Separate Query from Modifier(將查詢函數和修改函數分離) Parameterize Method(令函數攜帶參數) 4Separate Query from Modifier(將查詢函數和修改函數分離) 概要 某個函數既返回對象狀態值,又修改對象狀 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...