多線程(1)認識多線程

来源:http://www.cnblogs.com/mcgrady/archive/2017/06/20/7053674.html
-Advertisement-
Play Games

多線程在項目開發過程中非常非常重要,這個系列就來詳細總結一下,首先認識一下多線程。 windows為什麼要支持多線程 電腦的早期時代,操作系統沒有線程的概念,整個系統只運行著一個執行線程,其中包含操作系統代碼和應用程式代碼。只用一個執行線程的問題在於,長時間運行的任務會阻止其他任務的執行。例如16 ...


  多線程在項目開發過程中非常非常重要,這個系列就來詳細總結一下,首先認識一下多線程。

windows為什麼要支持多線程

電腦的早期時代,操作系統沒有線程的概念,整個系統只運行著一個執行線程,其中包含操作系統代碼和應用程式代碼。只用一個執行線程的問題在於,長時間運行的任務會阻止其他任務的執行。例如16位Windows的時代,列印文檔的應用程式很容易“凍結”整個機器。

Microsoft 在設計Windows NT這個版本的OS內核時,決定在一個進程中運行應用程式的每個實例。進程實際是應用程式的實例要使用的資源的集合。每個進程都被賦予了一個虛擬地址空間,確保一個進程中使用的代碼和數據無法由另一個進程訪問。這就確保了應用程式實例的健壯性。同時,進程訪問不了OS的內核代碼和數據;所以,應用程式代碼破壞不了操作系統的代碼和數據

如果應用程式發生死迴圈會發生什麼?如果機器只有一個CPU,它會執行死迴圈,不能執行其他任何程式。Microsoft 的解決方案就是線程。作為一個Windows概念,線程的職責是對CPU進行虛擬化。Windows為每個進程都提供了該進程專用的線程(功能相當於一個CPU)。應用程式的代碼進行死迴圈,與代碼關聯的進程會“凍結”,但其他進程(它們有自己的線程)不會凍結,它們會繼續執行。
線程很強大,因為它們使Windows即使在執行長時間運行的任務時,也能隨時響應。

所以多線程的發展歷史可以簡單總結為:沒有線程(只有一個執行線程)--->引入進程--->引入多線程 

線程的開銷

線程是給我們帶來好處的同時,也有性能的損失,包括空間上和時間上的。

1,空間上

創建一個線程需要載入以下資源:

  • 線程內核對象(thread kernel object),操作系統為系統中創建的每個線程都會分配並初始化這種數據結構,主要用於描述線程的屬性和線程上下文,上下文是一個記憶體塊,其中包含了CPU的寄存器集合。對於X86,X64和IA64的CPU來說,分別要使用700,1240和2500位元組的記憶體。
  • 線程環境塊(thread environment block,簡稱TEB),TEB是在用戶模式(應用程式能快速訪問的記憶體地址)中分配和初始化的一個記憶體塊,TEB耗用1個記憶體頁(X86和X64 CPU中是4KB,IA64 CPU是8KB)。
  • 用戶模式棧(user-mode stack),用戶模式棧用於存儲傳給方法的局部變數和實參,它還包含一個地址,指出當前方法返回時,線程接著應該從什麼地方執行,預設情況下,windows為每個線程的用戶模式棧分配1MB記憶體。
  • 內核模式棧(kernel-mode stack),當應用程式代碼向操作系統中的一個內核模式的函數傳遞實參時,就會使用到內核模式棧。出於安全的考慮,Windowd會把這些實參從線程的用戶模式棧複製到線程的內核模式棧。32windows 內核模式棧大小12KB,64位是24KB。
  • DLL線程連接(attach)和線程分離(detach)通知,Windows的一個策略是,任何時候在進程中創建線程,都會調用進程中載入的所有非托管DLL的DllMain方法,並向該方法傳遞DLL_THREAD_ATTACH標誌。同樣的,任何時候線程終止,都會調用進程中的所有非托管DLL的DllMain方法,並向該方法傳遞DLL_THREAD_DETACH標誌。

2,時間上

因為windows要在系統中的所有線程(邏輯CPU)之間共用物理CPU。在任何給定的時刻,windows只將一個線程分配給一個CPU,那個線程能運行一個“時間片”的長度。時間片到期,Windows就將上下文切換到另一個線程。

每個時間片的切換,windows都需要大概30ms的時間。

為什麼要使用多線程

1,可響應性,或稱用戶體驗,一般針對winform程式,可以將一些耗時的任務交給另一個線程去處理,使GUI線程能靈敏地響應用戶的輸入和操作。否則,界面會比較卡。

2,提升性能,由於windows每個CPU調度一個線程,多個CPU能並行調度線程,所以可以同時執行多個任務,從而提升性能。 

進程,線程和應用程式域的關係

在進一步學習多線程之前,很有必要來瞭解一下這三個概念,以及其中的關係。

1,名詞解釋

進程

或稱Process,可以簡單理解為一個.exe的實例。進程是windows系統中的一個基本概念,它包含著一個運行程式所需要的資源。進程之間是相對獨立的,一個進程無法訪問另一個進程的數據(除非利用分散式計算方式),一個進程運行的失敗也不會影響其他進程的運行,Windows系統就是利用進程把工作劃分為多個獨立的區域的。進程可以理解為一個程式的基本邊界。

線程

或稱Thread,可以簡單理解為虛擬CPU。線程是進程的基本執行單元,在進程入口執行的第一個線程被視為這個進程的主線程。在.NET應用程式中,都是以Main()方法作為入口的,當調用此方法時系統就會自動創建一個主線程。線程主要是由CPU寄存器、調用棧和線程本地存儲器(Thread Local Storage,TLS)組成的。CPU寄存器主要記錄當前所執行線程的狀態,調用棧主要用於維護線程所調用到的記憶體與數據,TLS主要用於存放線程的狀態信息。

應用程式域

或稱AppDomain,可以簡單理解為一組程式集的邏輯容器。CLR在初始化在初始化時創建第一個AppDomain(預設AppDomain),這個AppDomain在進程終止時被銷毀。.NET的程式集正是在應用程式域中運行的。一個進程可以包含有多個應用程式域,一個應用程式域也可以包含多個程式集。

 

2,進程,線程和應用程式域的關係

可以用以下兩幅圖和兩句話來總結。

1),一個進程可以包含多個線程和應用程式域。

2),一個線程可以穿梭在多個應用程式域中,但在某個時刻,線程只會處於一個應用程式域內。 

前臺線程和後臺線程的區別

1,前臺線程和後臺線程的區別在於,應用程式必須運行完所有的前臺線程才可以退出,而對於後臺線程,可以不考慮其是否運行完而直接退出並且不會拋出異常,所有的後臺線程在應用程式退出時就自動結束了。

2,預設情況下,主線程和使用Thread創建的線程都是前臺線程(使用線程池和Task創建的線程預設都是後臺線程),除非手動設置IsBackground= true。

多線程和非同步的區別

 多線程和非同步在很多時候被認為是同一個東西,都是為了讓主線程不需要等待而繼續執行。

但是從辯證關係上來看,兩者還是有區別的,可以用一句話來概括。

非同步是目的,多線程是實現非同步的其中的一種方式(比如還可以通過創建另一個進程實現非同步)。

 


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

-Advertisement-
Play Games
更多相關文章
  • C#編寫簡易的學生成績查詢 什麼是學生成績查詢系統? 使用C#語言編寫的一個可安裝的簡單CS系統,實現了用戶登錄,學生信息添加,成績修改,刪除,查詢等功能 開發環境 開發環境 visual studio2010(新版本2015,2017也可) visual studio2010(sql2008資料庫 ...
  • 背景:C# .Net MVC ,以及已經開發了近1年半的我,做了好久但是對於這個技術沒有總結,這是一個機會,寫寫我理解的東西吧。--以下內容參考了別人的文章 技術介紹: LINQ(Language Integrated Query,語言集成查詢)是一組用於C#和VB.NET語言的擴展,它允許編寫C# ...
  • 使用Thread類已經可以創建並啟動線程了,但是隨著開啟的線程越來越多,線程的創建和終止都需要手動操作,非常繁瑣,另一個問題是,開啟更多新的線程但是沒有用的線程沒有及時得到終止的時候,會占用越來越多的系統資源,影響性能。 所以,.net為我們引入了ThreadPool(線程池),我們只需要把要執行的 ...
  • 相關文章: "ASP.NET Core 使用 Hangfire 定時任務" ASP.NET Core Hangfire 在正式環境發佈之後,如果訪問 http://10.1.2.31:5000/hangfire/ 的話,會報 未授權錯誤,原因是 Hangfire 預設增加了授權配置。 解決方式: 增 ...
  • DotNetBar的視窗樣式丟失 C# 調用DotNetBar很方便,將DevComponents.DotNetBar2.dll和DevComponents.DotNetBar.Design.dll放在工程的Debug目錄下(下載地址)。將DevComponents.DotNetBar2.dll 直 ...
  • 我們先從最基礎的Thread說起。 創建並啟動線程 創建並啟動一個線程,如下代碼: 1 namespace ConsoleApplication17 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 var thread ...
  • 支付網關思考 目的 支付網關是為了屏蔽各種 支付工具之間的差異,對訂單系統行程一個統一的,標準的介面。如下圖所示 思路 事物補償機制 對賬 介面設計 1. 訂單狀態同步 bool UpdateOrderPaySatus(string orderId, int paySatas) 2. 預支付請求簽名 ...
  • 註意添加引用:System.Configuration; using System; using System.Collections.Generic; using System.Text; using System.Configuration; namespace DotNet.Utilities ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...