文章目录

  • 线程状态以及转换
    • 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…