跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

Linux 线程控制函数详解

综述由AI生成Linux 下线程控制的核心函数,包括获取线程 ID(pthread_self)、等待线程结束(pthread_join)、终止线程(pthread_exit)、取消线程(pthread_cancel)以及分离线程(pthread_detach)。文章阐述了 pthread 库在用户层提供接口,内核通过轻量级进程(LWP)实现调度的机制,并解释了 TCB 结构。此外,还对比了 C++11 标准线程库对原生 pthread 的封装,并通过代码示例验证了每个线程拥有独立栈结构的特性。

灵魂摆渡发布于 2026/3/30更新于 2026/5/2328 浏览
Linux 线程控制函数详解

Linux 线程控制函数

一、线程函数

1. 线程 ID

获取线程 ID,线程 ID 的名字叫做 tid。

#include <pthread.h>
pthread_t pthread_self(void);

返回值:该函数返回调用它的线程的线程 tid,返回类型为 pthread_t。

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <thread>
#include <string>
using namespace std;

// 将数字转为十六进制
string toHex(int num) {
    char ret[64];
    snprintf(ret, sizeof(ret), "%p", num);
    return ret;
}

// 循环打印 tid
void* threadroutine(void* args) {
    while (true) {
        sleep(2);
        cout << "thread id: " << toHex(pthread_self()) << endl;
    }
    return nullptr;
}

int main() {
    pthread_t tid;
    pthread_create(&tid, nullptr, threadroutine, nullptr);
    while (true) {
        cout << "creat a new thread, id: " << toHex(tid) << endl;
        sleep(1);
    }
    pthread_join(tid, nullptr);
    return 0;
}

终端输出示例

2. 线程等待

pthread_join:用于等待线程。

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

返回值:成功返回 0,失败返回错误码。

  • thread:表示要等待的目标线程的线程 tid。
  • retval:用于存储目标线程的退出状态,如果不需要获取退出状态,可以将其设置为 NULL。目标线程的退出状态是通过调用 pthread_exit 函数或者从线程函数中返回得到的。

3. 线程终止

pthread_exit 用于终止线程。

#include <pthread.h>
void pthread_exit(void* retval);

retval:这是一个 void* 类型的指针,用于传递线程的退出状态,这个值可以被其他线程通过 pthread_join 函数获取。如果线程不需要返回任何状态信息,可将其设置为 NULL。

需要注意的是,这里的参数是指针,不要指向一个局部变量,这里的栈空间在函数结束后会被系统收回。

4. 线程取消

pthread_cancel 用于向指定线程发送取消请求。

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

返回值:成功返回 0,失败返回错误码。 thread:表示要发送取消请求的目标线程的线程 tid。

线程取消示意图

5. 线程分离

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

返回值:成功返回 0,失败返回非零错误码。 thread:要分离的线程 tid。

在默认情况下,新创建的线程是可被等待的,线程退出后,需要对其进行线程等待,否则无法释放资源,造成系统泄漏。但如果我们并不关心线程的返回值,如我们仅用它完成一个动作,但我们不需要它的返回值,可被等待的性质就成为了一种负担。这个时候我们可以通过分离线程,在该线程退出的时候自动释放线程资源。

6. pthread 线程库的理解

在一些操作系统的早期版本中,内核主要以进程作为基本的调度和资源分配单位,从这个角度可以说在早期内核中没有像现在这样清晰明确的线程概念。而线程概念在用户层面上,pthread 库为我们提供了一系列用于线程操作的接口,极大地方便了开发者对线程的管理和使用。

但在现代操作系统的内核中,是有线程相关概念和实现的,内核支持将线程作为独立的调度实体进行管理。同时,线程的实现往往与轻量级进程紧密相关,轻量级进程在内核中拥有类似进程的一些数据结构,如进程控制块 task_struct 等。线程在底层很多时候是基于轻量级进程来实现的,以便在用户空间获得更好的并发效果和在内核空间获得资源调度等方面的支持。所以pthread 库为用户提供了便捷的线程管理接口,而内核中线程概念以轻量级进程等形式存在并进行实际的调度和管理等操作。

内核线程机制图

除了主线程,其他线程都存在于堆栈之间的内存映射段,其中有动态库,动态库中有 pthread.so 动态库,动态库中的方法通过调用内核来维护 TCB 结构体。

我们将线程管理起来也是根据先描述后组织的方法进行的,线程的控制块叫做 TCB(thread control block),线程的 tid 在现行的 NPTL(原生 POSIX 线程库)标准下我们可以简单的把它当做是线程控制块的地址,因为每个 TCB 的地址不同,所以它们的 tid 也不同。实际上如果我们用打印的方式是验证不了这个问题的,因为程序在链接时一定会链接一个叫做 ld 的动态库,这个库可以修饰虚拟地址。

TCB 地址验证

除了主线程,所有的其他线程的独立栈,默认都在共享区 pthread.so 库中。 从图中我们也清楚地表达了每个线程都有自己的局部存储和独立的栈结构,后面我们会来证明的。

二、线程控制拓展

1. C++11 线程库

C++11 的线程库 thread 实际上是封装了原生线程库 pthread.h。在 Linux 操作系统下,C++11 底层封装的是 Linux 的系统调用;在 Windows 操作系统下,C++11 封装的是 Windows 的系统调用。所以语言具有可移植性,因为语言库是通过条件编译先判断该系统是什么系统,然后对于不同的操作系统选择包含不同的 API 头文件。

C++11 线程库封装

C++11 跨平台实现

2. 每个线程都有自己独立的栈结构

线程函数的参数和返回值可以传递类对象,在这里我们通过传递类对象来验证每个进程都有自己独立的栈结构。

#include <iostream>
#include <pthread.h>
#include <vector>
#include <string>
#include <unistd.h>
using namespace std;

// 要创建的线程数量
#define NUM 3

// 定义一个可扩展类 ThreadInfo
class ThreadInfo {
public:
    ThreadInfo(const string &threadname) : threadname_(threadname) {}
public:
    string threadname_;
};

// tid 转十六进制
string toHex(pthread_t tid) {
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "%p", tid);
    return buffer;
}

void* threadroutine(void* args) {
    int i = 0;
    int num = 0;
    ThreadInfo *ti = static_cast<ThreadInfo*>(args);
    // 线程循环,每次打印线程名称、线程 ID、进程 ID、变量 num 以及 num 地址
    while (i < 10) {
        cout << ti->threadname_.c_str() << " is running, tid: " << toHex(pthread_self()) << ", pid: " << getpid() << ", num: " << num << ", &num: " << toHex((pthread_t)&num) << endl;
        i++;
        num++;
        usleep(10000);
    }
    delete ti;
    return nullptr;
}

int main() {
    vector<pthread_t> tids;
    for (int i = 0; i < NUM; i++) {
        pthread_t tid;
        ThreadInfo *ti = new ThreadInfo("Thread-" + to_string(i));
        pthread_create(&tid, nullptr, threadroutine, ti);
        tids.push_back(tid);
        usleep(1000);
    }
    // 线程等待
    for (auto tid : tids) {
        pthread_join(tid, nullptr);
    }
    return 0;
}

打印出来后我们可以发现 tid 相同的情况下,num 地址相同,tid 不同的情况下,num 地址也不同,证明每个线程都有自己独立的栈结构。

虽然线程都有自己独立的栈结构,但是它们之间如果想要通信也可以不搭建信道,因为只要定义一个全局的指针变量,就可以通过这个指针指向任何线程独立栈结构中的变量。所以说到底,线程还是在进程中的,它们之间的耦合性特别强。

目录

  1. Linux 线程控制函数
  2. 一、线程函数
  3. 1. 线程 ID
  4. 2. 线程等待
  5. 3. 线程终止
  6. 4. 线程取消
  7. 5. 线程分离
  8. 6. pthread 线程库的理解
  9. 二、线程控制拓展
  10. 1. C++11 线程库
  11. 2. 每个线程都有自己独立的栈结构
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • FLUX.1-dev FP8 量化技术解析:AI 绘画硬件优化实践
  • AI 小说创作平台搭建指南:本地部署智能写作助手
  • 豆包 AI 辅助学术论文搜索与解读实操指南
  • 本地训练专属大模型指南:基于 LLaMA-Factory 微调 DeepSeek-R1
  • 3661 可以被机器人摧毁的最大墙壁数目:离散化与线段树解法
  • Knife4j 4.5.0 与 Spring Boot 3.x 版本兼容问题解决方案
  • 智能桌面机器人快速搭建指南:ElectronBot 项目实践
  • LeetCode 146. LRU 缓存设计与代码详解
  • OpenClaw 在 Windows 环境下基于 Node.js 与 Kimi 的部署配置教程
  • 用初中数学理解 LLM 工作原理
  • 手把手教程:通过扣子平台部署OpenClaw并接入飞书,开启AI自动办公
  • AFFiNE 开源全能知识工作空间使用指南
  • Apache IoTDB 在 Kubernetes 集群中的部署与实践指南
  • C++ 二分查找算法详解与模板总结
  • 银河麒麟系统 Nginx Web 服务部署实战
  • Python 全栈开发学习路线与核心技术体系解析
  • C++ 智能指针完整详解
  • ESP32 小智 AI 机器人开发指南:本地唤醒与云端部署
  • AIGC 产品经理面试 100 道高频问题及答案解析
  • Git 仓库清理神器:git fetch -p 使用指南

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online