Linux-線程控制

線程等待

pthread_join()

pthread_join??是 Linux 系統中用于線程同步的重要函數,主要作用是等待指定線程結束并回收其資源。

基本功能

- 阻塞當前調用線程,直到目標線程執行結束。
- 回收目標線程的資源,避免產生“僵尸線程”。
- 可選地獲取目標線程的返回值。

函數原型

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);

- ?thread?:需要等待的目標線程 ID(由 ?pthread_create??返回)。
- ?retval?:用于存儲目標線程的返回值(若不需要,可設為 ?NULL?)。
- 返回值:成功返回 0,失敗返回非 0 錯誤碼。


使用示例

#include <pthread.h>
#include <stdio.h>void *thread_func(void *arg) {printf("子線程執行\n");return (void *)100; // 子線程返回值
}int main() {pthread_t tid;pthread_create(&tid, NULL, thread_func, NULL);void *ret;pthread_join(tid, &ret); // 等待子線程結束,獲取返回值printf("子線程返回值:%d\n", (int)ret);return 0;
}

注意事項

- 每個線程只能被 ?pthread_join??一次,多次調用會出錯。
- 若不調用 ?pthread_join??且未設置線程分離(?pthread_detach?),線程結束后資源不會被回收,會成為僵尸線程。
- 若目標線程已結束,?pthread_join??會立即返回并回收資源。

線程退出

方式1

return?

方式2

pthread_exit()pthread_exit??是 Linux 中用于線程退出的函數,定義在 ?<pthread.h>??頭文件中,用于終止當前線程的執行并返回退出狀態。

基本用法

- 函數原型:?void pthread_exit(void *retval);?
- 參數 ?retval?:指向線程退出狀態的指針,其他線程可通過 ?pthread_join??獲取該值。
- 作用:終止調用線程,釋放線程資源(但不會自動釋放線程創建時分配的堆內存等,需手動管理)。


關鍵特點

- 僅終止當前線程:與 ?exit??不同,?pthread_exit??只結束調用它的線程,不影響進程中其他線程的執行。
- 退出狀態傳遞:通過 ?retval??傳遞的狀態需為全局變量或動態分配的內存(避免棧內存被釋放),否則其他線程可能獲取到無效值。
- 與 ?return??的區別:在線程函數中使用 ?return??與 ?pthread_exit??效果類似,但 ?pthread_exit??更靈活(可在函數中任意位置調用)。

示例

#include <pthread.h>
#include <stdio.h>void *thread_func(void *arg) {int *result = malloc(sizeof(int));*result = 100;pthread_exit(result); // 線程退出并返回結果
}int main() {pthread_t tid;void *ret;pthread_create(&tid, NULL, thread_func, NULL);pthread_join(tid, &ret); // 獲取線程退出狀態printf("線程返回值:%d\n", *(int*)ret);free(ret); // 釋放動態分配的內存return 0;
}

上述示例中,線程通過 ?pthread_exit??返回動態分配的結果,主線程通過 ?pthread_join??獲取并釋放內存。

方式3

pthread_cancel()(線程的取消)

pthread_cancel??是 Linux 中用于取消線程執行的函數,屬于 POSIX 線程庫(pthread)的一部分,其作用是請求終止指定的線程。

基本語法

#include <pthread.h>
int pthread_cancel(pthread_t thread);

- 參數 ?thread?:目標線程的 ID(由 ?pthread_create??返回)。
- 返回值:成功返回 0,失敗返回非 0 錯誤碼(如 ?ESRCH??表示線程不存在)。

核心特點

1.?請求而非強制終止
pthread_cancel??只是發送一個“取消請求”,并非立即終止線程。線程是否響應、何時響應,取決于其“取消狀態”和“取消類型”。
2.?取消狀態(可通過 ?pthread_setcancelstate??設置)
- ?PTHREAD_CANCEL_ENABLE?(默認):線程允許響應取消請求。
- ?PTHREAD_CANCEL_DISABLE?:線程忽略取消請求,直到狀態改為允許。
3.?取消類型(可通過 ?pthread_setcanceltype??設置,僅當狀態為允許時有效)
- ?PTHREAD_CANCEL_DEFERRED?(默認):線程在“取消點”(如 ?sleep?、?read??等系統調用)處響應請求。
- ?PTHREAD_CANCEL_ASYNCHRONOUS?:線程立即響應請求(較少使用,可能導致資源未釋放)。

注意事項

- 線程被取消后,資源(如鎖、內存)需通過“線程清理函數”(?pthread_cleanup_push?/?pthread_cleanup_pop?)釋放,避免泄漏。
- 并非所有函數都是取消點,可通過 ?pthread_testcancel??主動檢查取消請求(手動創建取消點)。


示例:通過 ?pthread_cancel??取消一個延遲響應的線程,需確保線程在取消點處被終止。

注意

線程間的通信不僅僅只可以交流傳輸字符串或整數

這段代碼展示了如何在多線程中通過指針傳遞自定義對象(?Request??和 ?Response?),實現線程間的數據交互。主要功能是創建一個子線程,計算從 ?start_??到 ?end_??的整數和,并通過 ?Response??對象返回結果。

代碼解析

1.?自定義類

- ?Request?:封裝線程的輸入參數(計算范圍 ?start_?/?end_?、線程名稱 ?threadname_?)。

- ?Response?:封裝線程的輸出結果(計算總和 ?result_?、狀態碼 ?exitcode_?)。

2.?線程函數 ?sumCount?

- 接收 ?Request*??類型的參數,解析輸入范圍并循環計算總和。

- 每次循環打印當前進度(線程名+當前計算的數字),并通過 ?usleep(100000)??暫停0.1秒(方便觀察過程)。

- 計算完成后,創建 ?Response??對象存儲結果,釋放 ?Request??資源,返回 ?Response*?。

3.?主線程 ?main?

- 創建 ?Request??對象并傳入子線程,通過 ?pthread_create??啟動線程。

- 調用 ?pthread_join??等待子線程結束,獲取返回的 ?Response*??并打印結果,最后釋放資源。

 class Request{public:Request(int start, int end, const string &threadname): start_(start), end_(end), threadname_(threadname){}public:int start_;int end_;string threadname_;};class Response{public:Response(int result, int exitcode):result_(result),exitcode_(exitcode){}public:int result_;   // 計算結果int exitcode_; // 計算結果是否可靠};void *sumCount(void *args) // 線程的參數和返回值,不僅僅可以用來進行傳遞一般參數,也可以傳遞對象!!{Request *rq = static_cast<Request*>(args); //  Request *rq = (Request*)argsResponse *rsp = new Response(0,0);for(int i = rq->start_; i <= rq->end_; i++){cout << rq->threadname_ << " is runing, caling..., " << i << endl;rsp->result_ += i;usleep(100000);}delete rq;return rsp;}int main(){pthread_t tid;Request *rq = new Request(1, 100, "thread 1");pthread_create(&tid, nullptr, sumCount, rq);void *ret;pthread_join(tid, &ret);Response *rsp = static_cast<Response *>(ret);cout << "rsp->result: " << rsp->result_ << ", exitcode: " << rsp->exitcode_ << endl;delete rsp;return 0;}

線程及輕量化進程底層實現邏輯運用的是clone

clone?

?在 Linux 中,?clone??是一個系統調用,主要用于創建新的進程(或線程),與 ?fork??相比,它提供了更精細的控制能力,可以指定新進程與父進程共享哪些資源。
?
clone??的核心特點

- 靈活的資源共享:通過參數可以指定新進程是否共享父進程的內存空間、文件描述符表、信號處理等資源。例如,創建線程時通常會共享內存空間,而創建獨立進程時則不共享。
- 與 ?fork??的關系:?fork??可以看作是 ?clone??的一種特殊情況(?clone??省略部分參數時的簡化版),?fork??會復制父進程的幾乎所有資源,而 ?clone??可按需共享。

主要用途

- 創建線程(如 POSIX 線程 pthread 底層可能使用 ?clone?,共享內存空間)。
- 創建具有特定資源共享策略的進程,滿足特殊場景需求(如輕量級進程 LWP)。

簡單來說,?clone??是 Linux 中一個更底層、更靈活的進程/線程創建工具,通過控制資源共享粒度,適應不同的并發場景。

由于clone相對于用戶而言使用過于復雜,因此 Clone被包裝成庫供用戶使用,開發者將要調用的函數指針和棧區暴露出來給用戶使用,由于操作系統要對線程進行管理,而線程共用一個動態庫,因此副線程它主要存儲在共享區,而主線程及進程它是存放在內核的主線程棧中

TCB

在 Linux 中,TCB(Thread Control Block,線程控制塊) 是內核中用于管理線程狀態的核心數據結構,類似于進程的 PCB(Process Control Block),但專門用于線程。

TCB 的主要作用

- 存儲線程的基本信息,如線程 ID(TID)、狀態(運行、就緒、阻塞等)。
- 記錄線程的上下文(寄存器值、程序計數器等),用于線程切換時保存和恢復狀態。
- 關聯線程所屬的進程(進程 PCB),以及線程組信息。
- 管理線程的棧指針、信號掩碼、調度優先級等私有資源。

與 clone 的關系

當使用 ?clone??創建線程時(如指定 ?CLONE_THREAD?、?CLONE_VM??等標志),內核會為新線程創建一個 TCB,同時共享進程的部分資源(如內存空間)。TCB 是內核識別和調度線程的關鍵,確保每個線程能獨立被調度,同時與同進程其他線程協作。

簡單說,TCB 就是線程在內核中的“身份證”和“狀態檔案”,支撐線程的獨立運行和管理。

TID

在 Linux 中,TID(Thread ID,線程 ID) 是用于唯一標識線程的編號,類似于進程的 PID(Process ID),但專門針對線程。

TID 的特點

- 唯一性:系統中每個線程都有一個唯一的 TID,即使是同一進程內的不同線程,TID 也互不相同。
- 與 PID 的關系:在 Linux 中,線程本質上是輕量級進程(LWP),因此 TID 在內核中與 PID 共享同一編號空間(即 TID 也是一個“進程 ID”,但屬于線程級別的標識)。
- 線程組關聯:同一進程的所有線程屬于同一個線程組,線程組的領頭線程(通常是進程創建的第一個線程)的 TID 等于進程的 PID。

作用

- 內核通過 TID 識別和調度不同的線程。
- 用戶態可通過 ?gettid()??系統調用獲取當前線程的 TID,用于線程管理、調試等場景(如 ?ps -T??命令可查看進程內的線程 TID)。


例如,一個進程包含 3 個線程,它們會有各自不同的 TID,但共享同一個進程 PID(等于領頭線程的 TID)。

分散線程

Linux 中的分離線程(Detached Thread) 是一種特殊狀態的線程,核心特點是:

- 線程結束后會自動釋放資源(如棧、寄存器等),無需其他線程調用 ?pthread_join()??等待回收。
- 無法通過 ?pthread_join()??獲取其退出狀態。


主要用途

避免線程資源泄漏,適用于不需要等待其完成、也無需獲取結果的場景(如后臺日志打印、異步任務等)。

設置方式

1.?創建時指定:通過 ?pthread_attr_t??設置屬性為 ?PTHREAD_CREATE_DETACHED?。
2.?創建后設置:調用 ?pthread_detach(pthread_t thread)??函數將線程轉為分離狀態。

分離線程的核心是自動回收資源,簡化線程管理,避免手動回收的繁瑣。

pthread_detach??是 POSIX 線程庫中的一個函數,用于將指定線程設置為分離狀態(detached)。

核心作用

讓目標線程在結束時自動釋放所有資源(如棧空間、線程描述符等),無需其他線程通過 ?pthread_join??來等待或回收。

函數原型

#include <pthread.h>
int pthread_detach(pthread_t thread);

- 參數 ?thread?:要設置為分離狀態的線程 ID(由 ?pthread_create??返回)。
- 返回值:成功返回 0,失敗返回非 0 錯誤碼(如線程不存在)。

使用場景

適用于不需要獲取線程退出狀態、也無需等待其完成的場景(例如后臺服務線程、日志打印線程),避免資源泄漏。

注意點

- 線程一旦被分離,就無法再通過 ?pthread_join??獲取其狀態,調用會失敗。
- 可在線程創建后立即調用(通常由主線程或線程自身調用),也可在創建時通過屬性直接指定為分離狀態(更高效)。


簡單說,?pthread_detach??就是“告訴系統:這個線程結束后自己收拾干凈,不用別人管了”。??

線程私有化關鍵字__thread?

__thread??是 GCC 編譯器(GNU C 擴展)提供的關鍵字,用于聲明線程局部變量(Thread-Local Variables),實現線程空間私有化。它的作用是讓變量在每個線程中擁有獨立的副本,線程對變量的操作僅影響自身副本,不干擾其他線程。

主要特點

- 適用場景:主要用于 C/C++ 代碼,需配合 GCC 編譯器(或支持該擴展的編譯器,如 Clang)。
- 生命周期:變量的生命周期與線程一致,線程創建時初始化,線程結束時自動銷毀。
- 初始化限制:只能用常量初始化(不能用運行時動態計算的值)。

示例代碼

#include <stdio.h>
#include <pthread.h>
// 聲明線程局部變量,每個線程有獨立副本
__thread int var = 0;void* thread_func(void* arg) {int id = *(int*)arg;var = id; ?// 每個線程修改自己的副本printf("線程 %d 中的 var 值:%d\n", id, var);return NULL;
}int main() {pthread_t tid1, tid2;int id1 = 1, id2 = 2;pthread_create(&tid1, NULL, thread_func, &id1);pthread_create(&tid2, NULL, thread_func, &id2);pthread_join(tid1, NULL);pthread_join(tid2, NULL);return 0;
}


?輸出會顯示兩個線程的 ?var??值分別為 1 和 2,互不干擾。

與 ?thread_local??的關系

C11 標準引入了 ?thread_local??關鍵字,作為線程局部變量的標準語法,功能與 ?__thread??類似。?__thread??是 GCC 的非標準擴展,而 ?thread_local??是跨編譯器的標準實現(需編譯器支持 C11 或 C++11 及以上標準)。在支持標準的情況下,更推薦使用 ?thread_local??以保證可移植性。

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

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

相關文章

RAG優化秘籍:基于Tablestore的知識庫答疑系統架構設計

目錄一、技術架構設計二、雙流程圖解析橫向架構對比縱向核心流程三、企業級代碼實現Python檢索核心TypeScript前端接入YAML部署配置四、性能對比驗證五、生產級部署方案六、技術前瞻分析附錄&#xff1a;完整技術圖譜一、技術架構設計 原創架構圖 #mermaid-svg-3Ktoc4oH4xlbD6…

i.mx8 RTC問題

項目場景&#xff1a;需要增加外置RTC&#xff0c;保證時間的精準。問題描述&#xff1a;基本情況&#xff0c;外置i2c接口的RTC&#xff0c;注冊、讀寫都正常&#xff0c;但是偶發性重啟后&#xff0c;系統時間是2022&#xff0c;rtc時間是1970&#xff0c;都像是恢復了默認時…

數據集相關類代碼回顧理解 | utils.make_grid\list comprehension\np.transpose

目錄 utils.make_grid list comprehension np.transpose utils.make_grid x_gridutils.make_grid(x_grid, nrow4, padding2) make_grid 函數來自torchvision的utils模塊&#xff0c;用于圖像數據可視化&#xff0c;將一批圖像排列成一個網格。 x_grid&#xff1a;四維圖像…

C#中Static關鍵字解析

本文僅作為參考大佬們文章的總結。 Static關鍵字是C#語言中一個基礎而強大的特性&#xff0c;它能夠改變類成員的行為方式和生命周期。本文系統性總結static關鍵字的各類用法、核心特性、適用場景以及需要注意的問題&#xff0c;以幫助掌握這一重要概念。 一、Static關鍵字概…

通用綜合文字識別聯動 MES 系統:OCR 是數據流通的核心

制造業的 MES 系統需實時整合生產數據以調控流程&#xff0c;但車間的工單、物料標簽、質檢報告等多為紙質或圖片形式&#xff0c;傳統人工錄入不僅滯后&#xff0c;還易出錯&#xff0c;導致 MES 系統數據斷層。通用綜合文字識別借助 OCR 技術&#xff0c;成為連接這些信息與 …

【Linux 學習指南】網絡編程基礎:從 IP、端口到 Socket 與 TCP/UDP 協議詳解

文章目錄&#x1f4dd;理解源IP地址和目的IP地址&#x1f320; 認識端口號&#x1f309;端口號范圍劃分&#x1f309;理解"端口號"和"進程ID"&#x1f309;理解源端口號和目的端口號&#x1f309;理解socket&#x1f320;傳輸層的典型代表&#x1f309;認識…

React+Next.js+Tailwind CSS 電商 SEO 優化

一、項目背景與技術選型?1. 原始痛點?項目最初基于純 React 開發&#xff08;SPA 架構&#xff09;&#xff0c;存在三個致命問題&#xff1a;?搜索引擎爬蟲無法有效抓取動態渲染的商品詳情、分類頁內容&#xff1b;?單頁面應用 難以實現頁面級的 meta 定制&#xff0c;關鍵…

Process Lasso:提升電腦性能的得力助手

在日常使用電腦的過程中&#xff0c;我們常常會遇到這樣的問題&#xff1a;電腦運行緩慢、程序響應遲緩、多任務處理時卡頓不斷。這些問題不僅影響工作效率&#xff0c;還讓人感到非常煩躁。其實&#xff0c;這些問題很多時候是因為電腦的進程管理不夠優化。而Process Lasso正是…

AI驅動的大前端內容創作與個性化推送:資訊類應用實戰指南

在信息爆炸的時代&#xff0c;資訊類應用面臨兩大核心挑戰&#xff1a;一是如何高效生產海量優質內容&#xff0c;二是如何讓用戶從海量信息中快速獲取感興趣的內容。AI技術的介入正在重構資訊類應用的開發模式&#xff0c;從內容生產到用戶觸達形成全鏈路智能化。本文將從開發…

2025/7/16——java學習總結

Java IO 流全體系總結&#xff1a;從基礎到實戰的完整突破&#xff08;重寫&#xff09;一、基礎核心&#xff1a;字節流與字符流的底層邏輯&#xff08;一&#xff09;字節流&#xff1a;二進制數據的讀寫基礎操作字節輸入流&#xff1a;掌握 FileInputStream 單字節讀取細節&…

書籍自然數數組的排序(8)0715

題目給定一個長度為N的整型數組arr&#xff0c;其中有N個互不相等的自然數1~N&#xff0c;請實現arr的排序&#xff0c;但是不要把下標0~N-1位置上的數通過直接賦值的方式替換成1~N。解答 arr在調整之后應該事下標從0到N-1的位置上依次放著1~N&#xff0c;即arr[index] index …

【08】MFC入門到精通——MFC模態對話框 和 非模態對話框 解析 及 實例演示

文章目錄八、模態對話框 和 非模態對話框 創建及顯示8.1 對話框是怎樣彈出的8.2 模態對話框的創建及顯示8.3 非模態對話框的創建及顯示8.4 完整代碼下載八、模態對話框 和 非模態對話框 創建及顯示 Windows對話框分為兩類&#xff1a;模態對話框 和 非模態對話框。 模態對話框…

github上傳大文件(多種解決方案)

之前一直用vscode的上傳項目方法&#xff0c;這個方便之處在于不用打開git終端輸入各種命令&#xff0c;不過麻煩的是我一直無法拉取github上的遠程倉庫提交&#xff0c;每次只能更新已有的倉庫并且上傳的文件還不能太大&#xff0c;應該是不能超過100MB&#xff0c;而且直接在…

生活污水深度除磷的方法

生活污水中磷含量過多的危害大家都知道總磷是水質檢測的重要指標之一&#xff0c;在污水處理中生活污水往往都會出現總磷超標的現象。生活污水磷超標的危害是多方面的主要包括水體富營養化、危害水生生物、影響人類健康&#xff0c;以及可能引發藍藻水華等問題。除磷方法污水的…

Flutter瀑布流布局深度實踐:打造高性能動態圖片墻

本文將深入探討如何在Flutter中實現高性能瀑布流布局&#xff0c;解決動態高度內容展示的核心難題&#xff0c;并帶來卓越的用戶體驗。引言&#xff1a;瀑布流布局的魅力 瀑布流布局(Pinterest-style layout)已成為現代應用展示圖片和內容的黃金標準。它通過錯落有致的排列方式…

OpenCV 伽馬校正函數gammaCorrection()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 該函數用于對輸入圖像應用伽馬校正&#xff08;Gamma Correction&#xff09;&#xff0c;這是一種非線性的圖像處理技術&#xff0c;主要用于調整…

Linux-局域網構建+VLAN 劃分 + 端口 MAC-IP 綁定 + 靜態 DHCP

文章目錄1. 適用于家庭、工作室或小型企業的局域網構建2. VLAN劃分3. VLAN 劃分 端口 MAC-IP 綁定 靜態 DHCP跳轉→網絡管理基礎復習 1. 適用于家庭、工作室或小型企業的局域網構建 ? 一、硬件連線&#xff08;一次到位&#xff09; 光纖入戶 → 光貓/寬帶調制解調器光貓…

滲透測試路線

滲透測試學習路線報告&#xff08;從入門到高級&#xff09; 引言&#xff1a;滲透測試概述與學習路線設計 滲透測試作為網絡安全體系中的核心實踐環節&#xff0c;通過模擬真實攻擊者的技術手段與攻擊路徑&#xff0c;主動識別信息系統中的安全漏洞、評估防護機制有效性&#…

Node.js 中http 和 http/2 是兩個不同模塊對比

1. 核心模塊對比 特性http 模塊 (HTTP/1.1)http2 模塊 (HTTP/2)協議版本HTTP/1.1&#xff08;文本協議&#xff09;HTTP/2&#xff08;二進制協議&#xff09;多路復用不支持&#xff08;需多個 TCP 連接&#xff09;支持&#xff08;單連接多流&#xff09;頭部壓縮無HPACK 壓…

3DGS之COLMAP

COLMAP 在 3DGS 中起到了數據預處理和三維重建的關鍵作用&#xff0c;其處理流程包括特征提取與匹配、稀疏重建、稠密重建和輸出文件生成。結合 3DGS 的高斯分布建模和優化算法&#xff0c;COLMAP 提供了場景的幾何和相機信息&#xff0c;為實時渲染和三維重建奠定了基礎。一、…