Linux線程深度解析:從基礎到實踐

Linux線程深度解析:從基礎到實踐

一、線程基礎概念

1. 進程與線程定義

  • 進程:一個正在運行的程序,是操作系統資源分配的最小單位(擁有獨立的地址空間、文件描述符等資源),狀態包括就緒、運行、阻塞。
  • 線程:進程內部的一條執行路徑,是CPU調度的最小單位。一個進程可包含多個線程,共享進程的地址空間、全局變量、打開的文件等資源。

2. 核心優勢

  • 輕量化:線程創建和切換的開銷遠低于進程,適合高并發場景。
  • 資源共享:同一進程內的線程共享內存空間,數據交互無需跨進程通信(需注意同步問題)。

二、多線程編程核心接口

1. 關鍵頭文件與庫

  • 頭文件pthread.h(POSIX線程庫)
  • 編譯選項:需鏈接 pthread 庫,使用 -lpthread(如 gcc -o demo demo.c -lpthread

2. 線程創建:pthread_create

int pthread_create(pthread_t *thread,       // 輸出參數,存儲新線程IDconst pthread_attr_t *attr, // 線程屬性(NULL表示默認屬性)void *(*start_routine)(void *), // 線程入口函數void *arg                // 傳遞給入口函數的參數
);
  • 返回值:成功返回0,失敗返回錯誤碼(非0)。
  • 參數注意:傳遞局部變量地址時需注意生命周期(線程未啟動時變量可能已銷毀),推薦使用動態分配內存或值傳遞。

3. 線程退出:pthread_exit

void pthread_exit(void *retval); // retval為退出值,可被pthread_join獲取
  • 區別于exitexit終止整個進程,pthread_exit僅終止當前線程。

4. 線程等待:pthread_join

int pthread_join(pthread_t thread,        // 待等待的線程IDvoid **retval            // 接收退出值的指針(可NULL)
);
  • 作用:阻塞主線程直到目標線程結束,回收線程資源(避免內存泄漏)。

三、多線程編程實踐和常見問題

1. 單線程示例:主線程與子線程協作

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>void* thread_func(void *arg) {for (int i = 0; i < 3; i++) {printf("子線程運行: %d\n", i);sleep(1);}pthread_exit((void*)100); // 傳遞退出值
}int main() {pthread_t tid;void *ret;// 創建線程pthread_create(&tid, NULL, thread_func, NULL);// 等待線程結束pthread_join(tid, &ret);printf("子線程退出值: %d\n", (int)ret);return 0;
}

2. 多線程參數傳遞陷阱

錯誤示例:傳遞局部變量地址
void* print_index(void *arg) {int idx = *(int*)arg; // 危險!arg可能指向已銷毀的局部變量printf("索引: %d\n", idx);return NULL;
}int main() {pthread_t tid[5];int i;for (i = 0; i < 5; i++) {pthread_create(&tid[i], NULL, print_index, &i); // 所有線程共享i的地址}// 結果:打印的索引可能重復或超過5(i在循環結束后為5)return 0;
}
正確做法:值傳遞或動態分配
// 方法1:傳遞值(適用于簡單類型)
pthread_create(&tid[i], NULL, print_index, (void*)i); // 強制類型轉換,直接傳值// 方法2:動態分配內存(適用于復雜數據)
int *idx = malloc(sizeof(int));
*idx = i;
pthread_create(&tid[i], NULL, print_index, idx);

3. 數據競爭與同步問題

問題場景:多個線程操作全局變量
int counter = 0;
void* increment(void *arg) {for (int i = 0; i < 1000; i++) {counter++; // 非原子操作,可能導致結果錯誤}return NULL;
}// 運行結果:最終counter可能小于5000(線程間操作未同步)
解決方案:互斥鎖(Mutex)
#include <pthread.h>
pthread_mutex_t mutex;void* safe_increment(void *arg) {pthread_mutex_lock(&mutex); // 加鎖counter++;pthread_mutex_unlock(&mutex); // 解鎖return NULL;
}int main() {pthread_mutex_init(&mutex, NULL); // 初始化互斥鎖// 創建線程...pthread_mutex_destroy(&mutex); // 銷毀鎖return 0;
}

四、進程 vs 線程:核心區別對比

特性進程線程
資源分配獨立地址空間、文件描述符等共享進程資源(地址空間、全局變量)
調度單位進程線程
創建開銷高(需分配獨立資源)低(僅創建棧和線程控制塊)
切換開銷高(需切換地址空間等)低(僅切換寄存器和棧指針)
數據共享需IPC(管道、共享內存等)直接共享(需同步機制)
健壯性進程崩潰不影響其他進程線程崩潰可能導致進程崩潰

五、Linux線程實現機制

1. 線程實現方式

  • 用戶級線程:由用戶空間庫管理(如POSIX線程庫),內核 unaware,調度由用戶程序控制(缺點:一個線程阻塞會導致整個進程阻塞)。
  • 內核級線程:由內核直接調度(如Linux的輕量級進程LWP),支持并行執行(需多核CPU)。
  • Linux實現:采用輕量級進程(LWP),本質是內核中的進程,但共享父進程的地址空間。每個線程對應一個獨立的task_struct,但mm_struct(內存描述符)指向同一地址空間。

2. 線程與進程的內核視角

  • 在Linux中,線程被視為“共享資源的進程”,通過clone系統調用創建(可共享內存、文件描述符等資源)。
  • 查看線程:ps -eLf(LWP列顯示線程ID),或使用pthread_self()獲取當前線程ID。

六、思考:線程數量限制與調優

1. 影響線程數量的因素

  1. 虛擬地址空間:每個線程默認棧大小(如8MB)限制總線程數(32位系統約512線程,64位系統可更大)。
  2. 系統限制:通過ulimit -a查看max user processes(默認約1024)。
  3. 硬件資源:CPU核心數決定并行度,內存大小限制同時運行的線程數。

2. 理論計算示例

// 假設進程虛擬地址空間4GB,單個線程棧1MB:
最大線程數 ≈ 4GB / 1MB = 4096 個線程(實際因系統開銷會更低)

3. 調優建議

  • 減小棧大小:通過pthread_attr_setstacksize設置更小的棧(需謹慎,避免棧溢出)。
  • 動態創建銷毀:使用線程池復用線程,避免頻繁創建開銷。
  • 監控工具:用tophtop監控線程狀態,strace追蹤系統調用。

七、總結

線程是Linux高并發編程的核心工具,理解其與進程的區別、接口使用及同步機制是關鍵。在實際開發中,需根據場景選擇合適的并發模型(多進程/多線程/異步),并注意資源競爭、性能瓶頸等問題。通過合理設置線程屬性和使用同步工具,可充分發揮多核CPU性能,實現高效的并行計算。

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

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

相關文章

php學習筆記(全面且適合新手)

以下是專為 PHP 7.4 初學者設計的全面學習文檔&#xff0c;涵蓋基礎語法、細節語法和進階語法&#xff0c;結合 PHP 7.4 新特性與實戰案例&#xff0c;幫助系統掌握 PHP 開發&#xff1a; 為什么特地做7.4的筆記而不做8的&#xff1f;因為公司用的7.4&#xff0c;哈哈 一、基…

開源分布式數據庫(TiDB)

TiDB是由PingCAP 開發的開源分布式數據庫&#xff0c;兼容 MySQL 協議&#xff0c;集成了 HTAP&#xff08;混合事務和分析處理&#xff09;的能力&#xff0c;能夠同時處理在線事務和實時分析任務。 2015 年&#xff0c;TiDB 在 GitHub 創建&#xff0c;2025 年&#xff0c;Ti…

SpringBoot+Mybatis通過自定義注解實現字段加密存儲

&#x1f60a; 作者&#xff1a; 一恍過去 &#x1f496; 主頁&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社區&#xff1a; Java技術棧交流 &#x1f389; 主題&#xff1a; SpringBootMybatis實現字段加密 ?? 創作時間&#xff1a; 2025年04月…

Windows 10系統中找回MySQL 8的root密碼

以下是 在Windows 10系統中找回MySQL 8的root密碼 的詳細步驟&#xff1a; 步驟1&#xff1a;停止MySQL服務 按 Win R 輸入 services.msc&#xff0c;打開「服務」管理器。找到 MySQL80&#xff08;或其他自定義服務名&#xff09;&#xff0c;右鍵選擇 停止。 步驟2&#xf…

【計網】互聯網的組成

回顧&#xff1a; 互聯網(Internet)&#xff1a;它是一個專有名詞&#xff0c;是一個特定的互連網&#xff0c;它是指當下全球最大的、最開放的、由眾多網絡相互連接而形成的特定的的互連網&#xff0c;采用TCP/IP協議族作為通信規則。 一、互聯網的組成部分 從互聯網的工作方…

【vue3】黑馬程序員前端Vue3小兔鮮電商項目【八】

黑馬程序員前端Vue3小兔鮮電商項目【八】登錄頁面 登錄頁面的主要功能就是表單校驗和登錄登出業務。 賬號密碼 accountpasswordcdshi0080123456cdshi0081123456cdshi0082123456cdshi0083123456cdshi0084123456cdshi0085123456cdshi0086123456cdshi0087123456cdshi0088123456 …

C++學習:六個月從基礎到就業——C++11/14:右值引用與移動語義

C學習&#xff1a;六個月從基礎到就業——C11/14&#xff1a;右值引用與移動語義 本文是我C學習之旅系列的第三十九篇技術文章&#xff0c;也是第三階段"現代C特性"的第一篇&#xff0c;主要介紹C11/14中引入的右值引用和移動語義。查看完整系列目錄了解更多內容。 引…

基于Qlearning強化學習的電梯群控系統高效調度策略matlab仿真

目錄 1.算法仿真效果 2.算法涉及理論知識概要 2.1 Q-learning強化學習原理 2.2 基于Q-learning的電梯群控系統建模 3.MATLAB核心程序 4.完整算法代碼文件獲得 1.算法仿真效果 matlab2022a仿真結果如下&#xff08;完整代碼運行后無水印&#xff09;&#xff1a; 仿真操作…

31.軟件時序控制方式抗干擾

軟件時序控制方式扛干擾 1. 軟件時序控制抗干擾的時間邏輯2. 應用案例 1. 軟件時序控制抗干擾的時間邏輯 &#xff08;1&#xff09;將受軟件控制的功能或軟件檢測到的狀態一一羅列&#xff1b; &#xff08;2&#xff09;將其中的潛在干擾和敏感信號分開&#xff1b; &#x…

Ubuntu環境下使用uWSGI服務器【以flask應用部署為例】

0、前置內容說明 首先要知道WSGI是什么&#xff0c;關于WSGI服務器的介紹看這篇&#xff1a;WSGI&#xff08;Web Server Gateway Interface&#xff09;服務器 由于從Python 3.11開始限制了在系統級 Python 環境中使用 pip 安裝第三方包&#xff0c;以避免與系統包管理器&am…

d3_v7繪制折線圖

<!DOCTYPE html> <html><head><meta charsetutf-8><title>需求</title><script src"https://d3js.org/d3.v7.min.js"></script><style>* {margin: 0;padding: 0;}html, body {width: 100%;height: 100%;displ…

Hotspot分析(1):單細胞轉錄組識別信息基因(和基因模塊)

這一期我們介紹一個常見的&#xff0c;高分文章引用很高的一個單細胞轉錄組分析工具Hotspot&#xff0c;它可針對單細胞轉錄組數據識別有意義基因或者基因module&#xff0c;類似于聚類模塊。所謂的”informative "的基因是那些在給定度量中相鄰的細胞之間以相似的方式表達…

爬蟲準備前工作

1.Pycham的下載 網址&#xff1a;PyCharm: The only Python IDE you need 2.Python的下載 網址&#xff1a;python.org&#xff08;python3.9版本之后都可以&#xff09; 3.node.js的下載 網址&#xff1a;Node.js — 在任何地方運行 JavaScript&#xff08;版本使用18就可…

基于Springboot旅游網站系統【附源碼】

基于Springboot旅游網站系統 效果如下&#xff1a; 系統登陸頁面 系統主頁面 景點信息推薦頁面 路線詳情頁面 景點詳情頁面 確認下單頁面 景點信息管理頁面 旅游路線管理頁面 研究背景 隨著互聯網技術普及與在線旅游消費習慣的深化&#xff0c;傳統旅游服務模式面臨效率低、…

利用KMP找出模式串在目標串中所有匹配位置的起始下標

問題關鍵&#xff1a;完成首次匹配之后需要繼續進行模式匹配。 到這一步后&#xff0c;我們不能直接將j 0然后開始下一輪匹配&#xff0c;因為已經匹配過的部分&#xff08;藍色部分&#xff09;中仍然可能存在與模式串重疊的子串&#xff1a; 解決辦法&#xff1a; 找到藍…

RR(Repeatable Read)級別如何防止幻讀

在 MySQL 數據庫事務隔離級別中&#xff0c;RR&#xff08;可重復讀&#xff09; 通過 MVCC&#xff08;多版本并發控制&#xff09; 和 鎖機制 的組合策略來避免幻讀問題。 一、MVCC機制&#xff1a;快照讀與版本控制 快照讀&#xff08;Snapshot Read&#xff09; 每個事務啟…

Android運行時ART加載類和方法的過程分析

目錄 一,概述 二,ART運行時的入口 一,概述 既然ART運行時執行的都是翻譯DEX字節碼后得到的本地機器指令了&#xff0c;為什么還需要在OAT文件中包含DEX文件&#xff0c;并且將它加載到內存去呢&#xff1f;這是因為ART運行時提供了Java虛擬機接口&#xff0c;而要實現Java虛…

Javase 基礎加強 —— 02 泛型

本系列為筆者學習Javase的課堂筆記&#xff0c;視頻資源為B站黑馬程序員出品的《黑馬程序員JavaAI智能輔助編程全套視頻教程&#xff0c;java零基礎入門到大牛一套通關》&#xff0c;章節分布參考視頻教程&#xff0c;為同樣學習Javase系列課程的同學們提供參考。 01 認識泛型…

Oracle VirtualBox 在 macOS 上的詳細安裝步驟

Oracle VirtualBox 在 macOS 上的詳細安裝步驟 一、準備工作1. 系統要求2. 下載安裝包二、安裝 VirtualBox1. 掛載安裝鏡像2. 運行安裝程序3. 處理安全限制(僅限首次安裝)三、安裝擴展包(增強功能)四、配置第一個虛擬機1. 創建新虛擬機2. 分配內存3. 創建虛擬硬盤4. 加載系…

RAGFlow 接入企業微信應用實現原理剖析與最佳實踐

背景 近期有醫美行業客戶咨詢我們智能客服產品&#xff0c;期望將自己企業的產品、服務以及報價信息以企微應用的方式給到客戶進行體驗互動&#xff0c;提升企業運營效率。關于企業微信對接&#xff0c;我們分享下最佳實踐&#xff0c;拋磚引玉。效果圖如下&#xff1a; 這里也…