windows線程基礎

Windows線程機制詳解

線程的基本概念

在Windows操作系統中,線程是程序執行的最小單位。每個進程至少包含一個線程(主線程),但可以創建多個線程來并行執行任務。線程與進程的主要區別在于:

  1. 資源分配:進程擁有獨立的地址空間和系統資源,而線程共享進程的資源
  2. 調度單位:線程是CPU調度的基本單位,進程只是資源的容器
  3. 創建開銷:創建線程比創建進程的開銷小得多

Windows線程由以下幾個核心部分組成:

  1. 線程內核對象:操作系統用來管理線程的數據結構,包含線程狀態、優先級等信息
  2. 線程環境塊(TEB):包含線程特有的數據,如異常處理鏈、線程本地存儲等
  3. 用戶模式棧:用于存儲函數調用、局部變量等
  4. 內核模式棧:當線程調用系統服務時使用

線程的創建與終止

創建線程

在Windows中創建線程主要有兩種方式:

  1. 使用CreateThread API
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全屬性,通常為NULLSIZE_T dwStackSize,                      // 棧大小,0表示使用默認大小LPTHREAD_START_ROUTINE lpStartAddress,   // 線程函數地址LPVOID lpParameter,                      // 傳遞給線程函數的參數DWORD dwCreationFlags,                   // 創建標志,如CREATE_SUSPENDEDLPDWORD lpThreadId                       // 接收線程ID
);
  1. 使用C運行時庫的_beginthreadex
uintptr_t _beginthreadex(void *security,             // 安全屬性unsigned stack_size,        // 棧大小unsigned (__stdcall *start_address)(void *), // 線程函數void *arglist,              // 參數unsigned initflag,          // 初始狀態unsigned *thrdaddr          // 線程ID
);

重要說明

  • 如果使用C/C++運行時庫,建議使用_beginthreadex而非CreateThread,因為前者會正確初始化線程特定的C運行時庫數據
  • 線程函數必須返回DWORD并接受LPVOID參數
  • 創建線程后必須調用CloseHandle關閉線程句柄,否則會造成資源泄漏

線程終止

線程可以通過以下方式終止:

  1. 正常返回:線程函數執行return語句
  2. 調用ExitThread:立即終止當前線程
  3. 被其他線程終止:使用TerminateThread(不推薦)

最佳實踐

  • 應盡量避免使用TerminateThread,因為它不會給線程清理資源的機會
  • 線程應通過返回或調用ExitThread來正常終止
  • 主線程退出會導致整個進程終止,包括所有其他線程

線程調度與優先級

Windows使用基于優先級的搶占式調度算法。每個線程都有一個優先級,范圍從0(最低)到31(最高)。

線程優先級級別

Windows線程優先級分為以下幾個大類:

  1. 空閑優先級(0-6):用于后臺任務
  2. 普通優先級(7-15):大多數應用程序線程的默認級別
  3. 高優先級(16-22):用于時間關鍵任務
  4. 實時優先級(23-31):用于系統關鍵任務

可以通過以下API設置線程優先級:

BOOL SetThreadPriority(HANDLE hThread, int nPriority);
BOOL SetThreadPriorityBoost(HANDLE hThread, BOOL bDisablePriorityBoost);

時間片分配

Windows調度器為每個線程分配一個時間片(通常為20-30ms)。當時間片用完或更高優先級線程就緒時,當前線程會被搶占。

調度要點

  1. 高優先級線程總是先于低優先級線程執行
  2. 相同優先級的線程按時間片輪轉
  3. 前臺進程的線程會獲得稍長的時間片
  4. 系統會動態提升交互式線程的優先級

線程同步機制

多線程編程中最關鍵的問題是如何安全地訪問共享資源。Windows提供了多種同步機制:

1. 臨界區(Critical Section)

CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);EnterCriticalSection(&cs);
// 訪問共享資源
LeaveCriticalSection(&cs);DeleteCriticalSection(&cs);

特點

  • 只能用于同一進程內的線程同步
  • 效率高,不進入內核模式(在沒有競爭時)
  • 不支持超時等待

2. 互斥量(Mutex)

HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);WaitForSingleObject(hMutex, INFINITE);
// 訪問共享資源
ReleaseMutex(hMutex);CloseHandle(hMutex);

特點

  • 可以跨進程使用
  • 支持超時等待
  • 比臨界區開銷大

3. 事件(Event)

HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);// 線程1
SetEvent(hEvent);// 線程2
WaitForSingleObject(hEvent, INFINITE);

特點

  • 可用于線程間通知
  • 有手動重置和自動重置兩種類型
  • 支持跨進程使用

4. 信號量(Semaphore)

HANDLE hSem = CreateSemaphore(NULL, initialCount, maximumCount, NULL);WaitForSingleObject(hSem, INFINITE);
// 訪問受保護資源
ReleaseSemaphore(hSem, 1, NULL);CloseHandle(hSem);

特點

  • 控制對有限數量資源的訪問
  • 支持計數
  • 可以跨進程使用

線程局部存儲

線程局部存儲(TLS)允許每個線程擁有變量的獨立副本。Windows提供兩種TLS實現:

1. 動態TLS

DWORD tlsIndex = TlsAlloc();  // 分配TLS索引// 設置線程特定值
TlsSetValue(tlsIndex, pData);// 獲取線程特定值
void* pData = TlsGetValue(tlsIndex);TlsFree(tlsIndex);  // 釋放TLS索引

2. 靜態TLS

__declspec(thread) int tlsVar = 0;

比較

  • 動態TLS更靈活,但訪問速度稍慢
  • 靜態TLS效率更高,但數量有限(約1000個)
  • 靜態TLS在DLL中使用時需要注意初始化問題

線程池

創建和銷毀線程的開銷較大,Windows提供了線程池機制來優化:

工作項提交

TP_WORK* pWork = CreateThreadpoolWork(WorkCallback, pContext, NULL);
SubmitThreadpoolWork(pWork);
WaitForThreadpoolWorkCallbacks(pWork, FALSE);
CloseThreadpoolWork(pWork);

定時任務

TP_TIMER* pTimer = CreateThreadpoolTimer(TimerCallback, pContext, NULL);
// 設置2秒后執行,之后每1秒重復
ULARGE_INTEGER ulDueTime;
ulDueTime.QuadPart = -20000000LL;  // 2秒
SetThreadpoolTimer(pTimer, (PFILETIME)&ulDueTime, 1000, 0);

優勢

  • 自動管理線程數量
  • 減少線程創建銷毀開銷
  • 內置負載均衡

常見問題與調試

線程死鎖

死鎖通常發生在多個線程互相等待對方持有的鎖時。預防死鎖的方法包括:

  1. 按固定順序獲取鎖
  2. 使用超時機制
  3. 避免嵌套鎖

調試技巧

  1. WinDbg命令
~*kv         // 查看所有線程調用棧
!locks       // 查看臨界區狀態
  1. Visual Studio調試
  • 使用"并行堆棧"窗口查看線程關系
  • 設置數據斷點監視共享變量

性能優化建議

  1. 線程數量

    • CPU密集型任務:線程數≈CPU核心數
    • IO密集型任務:可適當增加線程數
  2. 避免過度同步

    • 縮小臨界區范圍
    • 使用無鎖數據結構
  3. 線程親和性

SetThreadAffinityMask(hThread, affinityMask);

可以減少CPU緩存失效,提高性能

總結

Windows線程機制提供了強大的并發編程能力,但也帶來了復雜性。理解線程的基本原理、掌握同步機制、合理使用線程池是編寫高效、穩定多線程程序的關鍵。在實際開發中,應特別注意資源同步和線程安全,避免競態條件和死鎖等問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/92246.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/92246.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/92246.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Numpy科學計算與數據分析:Numpy隨機數生成入門

Numpy隨機數生成實戰 學習目標 通過本課程,學員將掌握如何使用Numpy庫生成不同類型的隨機數,包括隨機整數、隨機浮點數以及從特定分布中抽樣的方法。本課程將通過理論講解與實踐操作相結合的方式,幫助學員深入理解Numpy在隨機數生成方面的強…

使用 C# 通過 .NET 框架開發應用程序的安裝與環境配置

文章目錄1. .NET介紹2. IDE2.1 Rider 安裝2.2 Visual Studio 安裝3. SDK安裝與環境配置3.1 單獨下載安裝 .NET SDK3.2 Visual Studio 工作負荷安裝SDK4. 相關問題4.1 我以前使用 Unity 寫 C# 腳本不需要額外的編譯器,為什么現在需要?1. .NET介紹 .NET 是…

Scikit-learn - 機器學習庫初步了解

目錄1. 主要算法分類1.1 監督學習 (Supervised Learning)1.2 非監督學習 (Unsupervised Learning)1.3 半監督學習 (Semi-Supervised Learning)1.4 強化學習 (Reinforcement Learning)1.5 遺傳算法 (Genetic Algorithm)2. 選擇合適的機器學習模型2.1 分類 (Classification)2.2 回…

關于 idea 里 properties 文件的中文亂碼問題

背景 你會發現 properties 文件里的中文可能會出現亂碼。 這個因為 properties 規范是使用 iso-8859-1 存儲的,不支持中文(也不支持西歐里法語、德語里奇怪的字母) properties 的標準制定于很早,所以沒考慮這么多,prop…

BVH文件 解析 解讀的python第三方類庫 推薦

我們面臨多個第三方庫選項用于解析BVH文件,根據您的列表,我將分析幾個關鍵庫的特點,并推薦最適合當前任務的庫。我們將基于以下標準進行選擇: ??功能性??:是否能準確解析關節角度數據,支持關鍵幀操作 ?…

uni-app X能成為下一個Flutter嗎?

哈嘍,我是老劉 老劉使用Flutter作為客戶端主要技術棧的這六七年的時間里,關于跨平臺開發的爭議和新技術始終沒有停過。 “一套代碼,多端運行”——這個讓無數開發者心動的承諾,究竟是技術革命還是美麗的謊言? 想象一…

Spring Cloud Gateway全棧實踐:動態路由能力與WebFlux深度整合

一、為什么需要下一代網關? 傳統網關的三大瓶頸: #mermaid-svg-Kdei9Io6KntYGQc4 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Kdei9Io6KntYGQc4 .error-icon{fill:#552222;}#mermaid-svg-…

MongoDB數據存儲界的瑞士軍刀:cpolar內網穿透實驗室第513號挑戰

軟件名稱:MongoDB 操作系統支持:Linux、Windows、macOS(Docker版全平臺通用!) 軟件介紹: MongoDB是一個基于分布式架構的NoSQL數據庫,擅長處理復雜數據類型(如嵌套對象、數組&…

SPI TFT全彩屏幕驅動開發及調試

簡介SPI(Serial Peripheral Interface)是一種廣泛使用的串行通信協議,常用于微控制器(MCU)與外圍設備(如傳感器、顯示屏、存儲器等)之間的通信。SPI具有全雙工傳輸、主從結構和較高的傳輸速率&a…

Linux學習—數據結構(鏈表2)

1.單向鏈表6.鏈表的查找在鏈表中找到指定的第一個元素沿用遍歷思想,每次訪問一個節點元素判斷是否為要找的節點符合條件返回該節點地址到最后沒有找到符號條件的節NULLlinknode *find_linklist(linknode *phead, datatype tmpdata) {linknode *ptmpnode NULL;ptmpn…

MySQL 備份利器 Xtrabackup 全解析:從部署到恢復的實戰指南

數據庫備份恢復是 DBA 的 “保命” 技能,生產業務不僅要保證有合適的備份策略,也要定期驗證備份的有效性和恢復演練流程,因為數據恢復和驗證可能會涉及多方合作,演練可以讓災難真正發生時,多方配合有條不紊的將數據恢復…

EAGLE-2:通過動態草稿樹加速語言模型推理

溫馨提示: 本篇文章已同步至"AI專題精講" EAGLE-2:通過動態草稿樹加速語言模型推理 摘要 現代 Large Language Models(LLMs)的推理過程既昂貴又耗時,而 speculative sampling 已被證明是一種有效的解決方案…

防水防塵防摔性能很好的智能三防手機,還有22000mAh大電池

在電力巡檢的崇山峻嶺間,在野外地質勘探的風沙深處,在應急救援的急風驟雨里,傳統智能設備因其固有的脆弱性與續航短板往往力不從心,甚至成為保障工作連續性的掣肘。而真正的智能三防手機應是一堵移動的堡壘,集堅不可摧…

Charles中文版抓包工具使用指南 提高API調試和網絡優化效率

在現代開發過程中,調試API、捕獲HTTP/HTTPS流量和優化應用的網絡性能已經成為開發者的常見任務。尤其是在調試復雜的API接口和分析網絡請求時,開發者需要一款高效且功能強大的工具。Charles抓包工具憑借其強大的網絡調試功能和易用的操作界面&#xff0c…

【C#補全計劃:類和對象(九)】接口

一、接口的概念1. 概念:接口是行為的抽象規范,也是一種自定義類型2. 接口聲明規范:(1)不包含成員變量(2)只包含屬性、方法、索引器、事件(3)成員不能被實現(4…

SRS簡介及簡單demo

SRS介紹 SRS(Simple Realtimes Server)是一款開源的實時流媒體服務器,專注于解決直播、實時互動等場景的流媒體傳輸問題。SRS 的設計目標是 “簡單、穩定、高效”,專門針對實時流媒體協議(如 RTMP、HLS、HTTP-FLV、WebRTC 等)進行優化,專注于解決 “低延遲、高并發” 的…

python基礎:數據解析BeatuifulSoup,不需要考慮前端形式的一種獲取元素的方法

1.beatuifulSoup 基本用法 beautifulSoup(簡稱bs4)是python的一個第三方庫,用于解析html和xml文檔中提取數據的python庫。它能夠將復雜的文檔轉化為樹形結構,方便快速定位和提取所需數據以及查找和修改,常常與爬蟲框架…

Ubuntu共享文件夾權限設置

在Ubuntu中設置共享文件夾的權限(只讀、讀寫、無權限),主要通過兩種方式實現:?文件系統權限?和?Samba共享配置?。以下是詳細步驟:?一、文件系統權限設置(基礎權限)?1. ?修改文件夾所有權…

小程序點擊菜單欄實現樣式動態切換

小程序點擊菜單欄背景樣式動態切換 前言:今天做一個小程序項目,要做一個菜單欄動態切換的功能,因為這種需求很常見,這次干脆記錄一下,幫助別人的同時,自己下次也可以直接照搬使用。 效果截圖如下&#xff1…

掌握工程化固件燒錄,開啟你的技術進階之路-FPGA ISE(xilinx)

1、電腦需先行安裝ISE14.7。若已完成安裝,此步驟可略過;若尚未安裝,在后續章節會介紹如何安裝ISE,由于ISE14.7的安裝程序體量龐大,可借助U盤進行傳輸。同時,電腦需預留至少30G的存儲空間以用于安裝該程序。…