【C/C++】線程狀態以及轉換

文章目錄

  • 線程狀態以及轉換
    • 1 基本狀態
      • 1.1 新建(New)
      • 1.2 就緒(Ready / Runnable)
      • 1.3 運行中(Running)
      • 1.4 阻塞/等待(Blocked / Waiting / Sleeping)
      • 1.5 掛起(Suspended)
      • 1.6 終止(Terminated / Dead / Exit)
      • 注意點
    • 2 狀態轉換
      • 2.1 C/C++ 線程狀態轉換圖(基于 Linux/POSIX 和 `std::thread`)
      • 2.2 狀態轉換說明
      • 2.3 示例:多個狀態的轉換代碼
    • 3 調試
      • 3.1 Linux 中線程/進程的典型狀態碼
      • 3.2 深入 `/proc/[pid]/task/` 查看線程狀態
      • 3.3 狀態之間的實際轉換(C++ 映射)
      • 3.5 調試技巧
    • 總結:線程狀態的決定者是誰?

線程狀態以及轉換

線程的基本狀態通常用于描述線程在程序執行過程中的生命周期。


1 基本狀態

1.1 新建(New)

  • 說明:線程對象已經創建,但尚未啟動。
  • 示例(C++):std::thread t(myFunction);(如果尚未調用 join()detach()

1.2 就緒(Ready / Runnable)

  • 說明:線程已經準備好運行,但由于 CPU 正忙,暫時未被調度執行。
  • 特征:已具備運行條件,等待調度。

1.3 運行中(Running)

  • 說明:線程正在由 CPU 調度并執行任務。
  • 特征:只有一個線程能在某一時刻占用一個 CPU 核心運行。

1.4 阻塞/等待(Blocked / Waiting / Sleeping)

  • 說明:線程暫時無法繼續運行,處于等待某些資源或事件狀態。

  • 常見原因:

    • 等待鎖(mutex)釋放
    • 等待條件變量(std::condition_variable
    • 調用了 sleep_for() / sleep_until()
    • 等待 I/O 操作完成

1.5 掛起(Suspended)

  • 說明:線程被人為暫停,暫時不會被調度(某些系統中才存在,如 Windows)。
  • 補充:這不是所有系統都顯式支持的狀態。

1.6 終止(Terminated / Dead / Exit)

  • 說明:線程執行完任務或被強制終止,生命周期結束。

  • 注意事項:

    • 線程終止后不能被重啟。
    • C++ 中,必須在適當時機調用 join()detach(),否則可能引發資源泄露。

注意點

  • std::thread 構造后即啟動,不能“延遲啟動”。
  • join():主線程等待子線程執行完畢。
  • detach():子線程后臺運行,主線程不再關心其狀態。
  • 未調用 join()detach() 就析構 std::thread,會導致程序崩潰。

2 狀態轉換

在 C/C++ 中,線程狀態的轉換并不像 Java 那樣有統一的虛擬機控制模型,而是依賴于底層操作系統(如 Linux、Windows)調度機制。C++ 本身通過 std::thread 提供了對系統線程(如 POSIX Threads 或 Windows Threads)的封裝,但不顯式暴露線程狀態。

結合操作系統線程模型,理解 C/C++ 中線程狀態的轉換路徑。


2.1 C/C++ 線程狀態轉換圖(基于 Linux/POSIX 和 std::thread

簡單版本

 [New] ↓[Ready] ? [Running] → [Terminated]↑          ↓[Blocked] ←---
 +--------+       thread constructor|  New   | --------------------------++--------+                           ||                               v|                        +-------------+|        OS調度          |   Runnable  |+----------------------> +-------------+|             |v             |+--------------+      | 被搶占或 yield|   Running    | <----++--------------+|+----------------------+------------------------------+|                      |                              |v                      v                              v
[Waiting on lock]   [Waiting on cond_var]          [sleep_for / sleep_until]Blocked              Waiting (CondVar)             Sleeping+                      +                              +|                      |                              |+---------> 信號/條件滿足/定時器超時  <---------------+|v+--------------+|   Runnable   |+--------------+|v+--------------+|   Running    |+--------------+|執行結束 or 異常|v+--------------+| Terminated   |+--------------+

Linux 實際版

            +-------------+|   Running   | <--------++-------------+          ||        ^            |preempt    schedule       |v        |            |+-------------+           ||   Runnable   | ---------++-------------+|+------+------+|             |+-------+     +--------+| Sleep |     |  Disk  ||  (S)  |     | Sleep  |+-------+     |  (D)   ||         +--------+|               |v               v+---------------------+|     Runnable        |+---------------------+(via wakeup or I/O completion)

2.2 狀態轉換說明

狀態名稱觸發條件示例代碼
New → Runnable創建線程對象 std::thread t(...)std::thread t(myFunc);
Runnable → Running被操作系統調度自動完成,無需顯式操作
Running → Blocked獲取互斥鎖失敗(如 mutex.lock()std::unique_lock<std::mutex> lock(m);
Running → Waiting調用 condition_variable.wait()cv.wait(lock);
Running → Sleeping調用 std::this_thread::sleep_for(...)std::this_thread::sleep_for(1s);
Blocked/Waiting/Sleeping → Runnable條件滿足/超時/鎖釋放由 OS 處理,代碼中不可見
Running → Terminated線程函數返回/異常函數結束或 return

2.3 示例:多個狀態的轉換代碼

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>std::mutex mtx;
std::condition_variable cv;
bool ready = false;void worker() {std::unique_lock<std::mutex> lock(mtx);std::cout << "Worker: waiting...\n";// Running → Waiting(掛起等待條件變量)cv.wait(lock, [] { return ready; });std::cout << "Worker: resumed and working...\n";// Running → Sleepingstd::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Worker: finished.\n";// → Terminated
}int main() {std::thread t(worker);std::this_thread::sleep_for(std::chrono::seconds(2));{std::lock_guard<std::mutex> lock(mtx);ready = true;std::cout << "Main: notifying worker...\n";}cv.notify_one();t.join();
}

執行結果

Worker: waiting...
Main: notifying worker...
Worker: resumed and working...
Worker: finished.

3 調試

3.1 Linux 中線程/進程的典型狀態碼

運行命令如:

ps -o pid,tid,stat,comm -L -p <pid>

或者使用 top,會看到類似以下狀態碼:

例如輸出:

  PID   TID STAT COMMAND
12345 12345 Ss   my_program
12345 12346 Sl   my_program
12345 12347 Rl   my_program
12345 12348 S    my_program
  • Ss:主線程,sleeping 且為 session leader。
  • Sl:sleeping + 多線程(L)。
  • Rl:runnable + 多線程(L)。
  • S:普通 sleeping 線程。
狀態碼含義說明
RRunning / Runnable正在運行,或在運行隊列中等待調度
SSleeping (Interruptible)可中斷的睡眠,等待事件或條件,如 sleep()read()
DUninterruptible sleep不可中斷的睡眠(通常為 IO),如等待磁盤或網絡
TTraced / Stopped被調試器暫停或收到 SIGSTOP 信號
ZZombie僵尸進程,子進程已終止但父進程未調用 wait()
XDead非正常終止(很少見)

3.2 深入 /proc/[pid]/task/ 查看線程狀態

Linux 把每個線程當作一個任務(task),在 /proc/[pid]/task/ 下有所有線程的子目錄:

ls /proc/<pid>/task/

然后可以查看每個線程狀態:

cat /proc/<pid>/task/<tid>/status

輸出中有一行:

State:	S (sleeping)

其他可能值包括:

  • R (running)
  • D (disk sleep)
  • T (stopped)
  • Z (zombie)

3.3 狀態之間的實際轉換(C++ 映射)

Linux 狀態對應 C++ 場景
R (Runnable)正在執行或準備被調度,CPU 調度隊列中
S (Sleeping)std::this_thread::sleep_for、等待條件變量、I/O 等
D (Disk Sleep)被阻塞在磁盤或網絡 I/O(不可中斷)
T (Stopped)被調試或 SIGSTOP 暫停
Z (Zombie)線程/進程退出但未被 join()/wait()

3.5 調試技巧

  1. htop 可視化線程狀態
htop
# F2 -> Display options -> Show custom thread names (如你設置了)
  1. gdb 附加調試線程狀態
gdb -p <pid>
info threads
  1. perf top 查看哪些線程/函數在消耗 CPU

總結:線程狀態的決定者是誰?

決定因素狀態
程序員代碼睡眠、等待、join 等顯式操作
操作系統調度器Running / Runnable 切換、搶占等
鎖競爭Blocked(mutex、spinlock)

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

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

相關文章

Python與自動駕駛數據集處理:構建智能駕駛的基石

Python與自動駕駛數據集處理:構建智能駕駛的基石 在自動駕駛技術的快速發展中,數據始終是最核心的驅動力。自動駕駛系統依賴于大量的傳感器數據(激光雷達、攝像頭、GPS等),通過深度學習算法不斷優化決策,使車輛能夠自主感知、理解道路環境并做出合理決策。而 Python 作為…

【菜狗work前端】小程序加if判斷時不及時刷新 vs Web

零、前提&#xff1a; 實現input輸入數字不大于10000&#xff08;需要配合typenumber&#xff0c;maxlength5&#xff0c;這里沒寫&#xff09; 一、探究代碼&#xff1a; <input v-model"model1" input"changeModel1" placeholder"請輸入拒收件…

【Netty】- NIO基礎2

阻塞模式 客戶端代碼 public class Client {public static void main(String[] args) throws IOException {SocketChannel sc SocketChannel.open();sc.connect(new InetSocketAddress("localhost", 8080));// sc.write(Charset.defaultCharset().encode("he…

【WebRTC】源碼更改麥克風權限

WebRTC源碼更改麥克風權限 倉庫: https://webrtc.googlesource.com/src.git分支: guyl/m125節點: b09c2f83f85ec70614503d16e4c530484eb0ee4f

cocos creator使用jenkins打包微信小游戲,自動上傳資源到cdn,windows版運行jenkins

cocos 版本2.4.11 在windows上jenkins的具體配置和部署&#xff0c;可參考上一篇文章cocos creator使用jenkins打包流程&#xff0c;打包webmobile_jenkins打包,發布,部署cocoscreator-CSDN博客 特別注意&#xff0c;windows上運行jenkins需要關閉windows自己的jenkins服務&a…

力扣刷題(第三十六天)

靈感來源 - 保持更新&#xff0c;努力學習 - python腳本學習 多數元素 解題思路 這道題是要找出數組中出現次數超過一半的元素。有幾種不同的方法可以解決這個問題&#xff1a; 哈希表統計法&#xff1a;遍歷數組&#xff0c;用哈希表統計每個元素的出現次數&#xff0c;…

關于讀取CH584單片機的IO電平出現到的烏龍

本來是調用的庫里的 uint8_t get_wake_up_sta (void) {return GPIOB_ReadPortPin(GPIO_Pin_10);//return cc_gpio_get_in_io (WAKUP_CH);} 然后讀出來是0&#xff0c;我都配置上拉了。 搞不到原因。 最后是CH584單片機只有0和非零兩種狀態&#xff0c;讀出來1024被轉換成無…

Opencv常見學習鏈接(待分類補充)

文章目錄 1.常見學習鏈接 1.常見學習鏈接 1.Opencv中文官方文檔 2.Opencv C圖像處理&#xff1a;矩陣Mat 隨機數RNG 計算耗時 鼠標事件 3.Opencv C圖像處理&#xff1a;亮度對比度飽和度高光暖色調陰影漫畫效果白平衡浮雕羽化銳化顆粒感 4.OpenCV —— 頻率域濾波&#xff…

anaconda、miniconda、conda的關系及miniconda安裝

anaconda、miniconda、conda的關系及miniconda安裝 文章目錄 前言正文定義關系Linux安裝miniconda新建一個python3.8環境 參考 前言 本文用于記錄關于Anaconda、conda和Miniconda的定義及其關系的總結123&#xff1a; 正文 定義 conda 一個跨平臺的開源包管理和環境管理工具…

2024-2025年AI領域重大事件深度解析:技術革命、產業重構與未來挑戰

一、技術突破&#xff1a;從多模態到具身智能的跨越式演進 1. 生成式AI的“核爆級”升級 多模態融合&#xff1a;OpenAI的GPT-4o實現文本、圖像、語音的實時交互&#xff0c;GPQA基準測試得分達87.7%&#xff0c;在科學推理和編程任務中表現卓越1。谷歌的Gemini 2.0 Flash支持…

城市地下“隱形衛士”:激光甲烷傳感器如何保障燃氣安全?

城市“生命線”面臨的安全挑戰 城市地下管網如同人體的“血管”和“神經”&#xff0c;承載著燃氣、供水、電力、通信等重要功能&#xff0c;一旦發生泄漏或爆炸&#xff0c;將嚴重影響城市運行和居民安全。然而&#xff0c;由于管線老化、違規施工、監管困難等問題&#xff0…

融云 uni-app IMKit 上線,1 天集成,多端暢行

融云 uni-app IMKit 正式上線&#xff0c;支持一套代碼同時運行在 iOS、Android、H5、小程序主流四端&#xff0c;集成僅需 1 天&#xff0c;并可確保多平臺的一致性體驗。 融云 uni-app IMKit 在 Vue 3 的高性能加持下開發實現&#xff0c;使用 Vue 3 Composition API&#x…

《Claude:人工智能界的璀璨新星》

一、Claude 登場&#xff1a;AI 新時代的震撼開篇 在科技飛速發展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已經成為推動社會進步和創新的核心力量。從智能語音助手到自動駕駛汽車&#xff0c;從圖像識別技術到自然語言處理&#xff0c;AI 正以驚人的速度滲透到我…

Python中tqdm進度條工具和enumerate函數的使用詳解

tqdm進度條工具 tqdm 是 Python 中一個非常流行的 進度條顯示工具庫&#xff0c;常用于迭代操作的可視化&#xff0c;比如訓練神經網絡、批量數據處理等任務。 一、tqdm 是什么&#xff1f; tqdm 全稱是 taqaddum&#xff08;阿拉伯語&#xff0c;意為“進展”&#xff09;&a…

yum命令常用選項

刷新倉庫列表 sudo yum repolist清理 Yum 緩存并生成新的緩存 sudo yum clean all sudo yum makecache驗證 EPEL 源是否已正確啟用 sudo yum repolist enabled安裝軟件包 sudo yum install <package-name> -y更新軟件包 sudo yum update -y僅更新指定的軟件包。 su…

linux debug技術

Linux是當今應用最廣泛的免費和開源操作系統&#xff0c;它是一個復雜的分布式操作系統。它的內核的強大和靈活性已成為引用它的原因之一。在掌握Linux內核的過程中&#xff0c;調試工具可以幫助開發人員獲得更深入的反思和理解。下面有25種不可或缺的Linux內核調試工具&#x…

【LinkedList demo 內部類講說】

LinkedList demo 內部類講說 1. Node節點2.MyLinkedList3. LinkedListTest 測試類 1. Node節點 public class Node<T> {private Node<T> pre;private Node<T> next;private T data;public Node() {}public Node getPre() {return pre;}public void setPre(N…

html主題切換小demo

主題切換功能為網頁和應用程序提供了多樣化的視覺風格與使用體驗。實現多主題切換的技術方案豐富多樣&#xff0c;其中 CSS 變量和 JavaScript 樣式控制是較為常見的實現方式。 以下是一個簡潔的多主題切換示例&#xff0c;愿它能為您的編程之旅增添一份趣味。 代碼展示 <…

【數據結構】

一、架構梳理 線性&#xff08;1:1) 線性表 順序存儲 –> arr 鏈式存儲 –> 指針 &#xff08;有頭&#xff0c;無頭&#xff09; 有頭是指有一個不存數據的頭&#xff0c;始終作為這個鏈表的起點。 會更加簡單&#xff0c;無頭的話&#xff0c;更改首部節點會麻煩。 頭…

UML學習指南:從零入門到實戰應用

為零基礎學習者設計的UML技術文檔&#xff0c;旨在通過詳細解釋和實際案例&#xff0c;從零開始掌握UML。 UML學習指南&#xff1a;從零入門到實戰應用 目錄 引言&#xff1a;UML是什么&#xff1f;為什么學習UML&#xff1f; 1.1 什么是UML&#xff1f;1.2 為什么我們需要UM…