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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...