@bit::Shadow
✧(≖ ◡ ≖✿
目录
[线程监视ps -aL](#线程监视ps -aL)
[pthread_attr_t* attr的部分默认属性](#pthread_attr_t* attr的部分默认属性)
POSIX线程
POSIX线程通常简称为pthread(这也是几乎所有线程接口的前缀),是POSIX(可移植操作系统接口)标准定义的多线程API规范。为Linux/Unix等许多系统提供了统一的线程创建、管理和同步接口。
线程控制必要的库链接-lpthread
在涉及线程链接时 需要加以 "-lpthread" 用于链接第三方库。(这是线程控制的基础)
为什么需要链接,先前我们使用的为什么不需要呢?
因为编译器默认不会把libpthread.so拉进来所以需要手动指定,否则虽然在编译期不会报错但是在链接期会报"undeclare "的错误。
第三方库的位置

phtread.h头文件
pthread.h内涵盖了所有线程接口(如:phtread_create() phtread_join()),类型(如:pthread_t、pthread_mutex_t、pthread_cond_t )、常量(如:**PTHREAD_CREATE_JOINABLE**设置线程可被等待回收♻️)。
头文件位置
bash
w@instance-qhw6x01g:~/e2026/June/6-22$ ls -al /usr/include/pthread.h
-rw-r--r-- 1 root root 48376 May 26 2025 /usr/include/pthread.h
线程监视ps -aL
cpp
#include<iostream>
#include<unistd.h>
void test1();void test2();void test3();void test4();void test5();
int main()
{
test1();
return 0;
}
void* routine1(void*)
{
sleep(5);
return nullptr;
}
void test1()
{
//创建两个线程使得睡眠并 可检测
pthread_t pd1,pd2;
pthread_create(&pd1,nullptr,routine1,(void*)"空1");
pthread_create(&pd2,nullptr,routine1,(void*)"空2");
//wait
pthread_join(pd1,nullptr);
pthread_join(pd2,nullptr);
}
输出
PID:进程ID相同意味着隶属同一块进程。
LWP(Light Weight Process):"轻量级进程"作为CPU调度的ID------与用户级使用标识ID区分开。
|---------------|----------------------------------------------------------------------|
| PID | 进程 ID(Process ID)。同一进程下的所有线程,其 PID 相同。 |
| LWP | 轻量级进程 ID (Lightweight Process ID)。这是内核视角下的线程 ID,是每个线程的唯一标识符。 |
| TIME | 该线程累计占用的 CPU 时间。 |
| COMMAND | 线程所属的进程名(所有线程显示相同名称)。 |
示例
bash
w@instance-qhw6x01g:~/e2026/June/6-22$ ps -aL
PID LWP TTY TIME CMD
11586 11586 pts/0 00:00:00 a.out
11586 11588 pts/0 00:00:00 a.out
11586 11589 pts/0 00:00:00 a.out
11658 11658 pts/1 00:00:00 ps
基本线程控制
创建等待分离
线程创建
cpp
int pthread_create(pthread_t* thread, \
const pthread_attr_t* attr, \
void*(*start_routine)(void*), void* arg);
//create的末尾'e'不要落下!
pthread_t(unsigned long ) thread:输出型参数,输出线程ID。(栈下动态库的独立线程的独立分配区的起始地址)
const pthread_attr_t* attr:设置创建线程的属性(通常无需设置nullptr默认即可)。
void*(*start_routine)(void*):函数指针返回值参数均为void*。
void* arg:传递给第三个函数的参数。
成功返回0,失败错误码被设置。
pthread_attr_t* attr的部分默认属性
|----------|---------------------------|-------------------------------|
| 分离状态 | PTHREAD_CREATE_JOINABLE | 线程是可等待的(需要 pthread_join 回收) |
| 调度策略 | SCHED_OTHER | 分时调度策略(CFS,完全公平调度器) |
| 栈大小 | 通常 8 MB | 可用 ulimit -s 查看系统默认栈大小 |
各线程专属栈大小查询ulimit -s
cpp
w@instance-qhw6x01g:~/e2026/June/6-22$ ulimit -s
stack size (kbytes, -s) 8192
线程等待
cpp
int pthread_join(pthread_t thread, void** retval);
等待目标新线程,并使用二级指针接受其一级指针返回值(void*类型)。(例如对线程名字的带出)
一次只能等待一个线程。
成功返回0,否则错误码被设置。
当前线程终止
pthread_exit(void* retval); // 适用于在线程的任何位置终止该线程并返回reval。
与return (void*)retval;等价。
cpp
void pthread_exit(void* retval);
线程取消
cpp
int pthread_cancel(pthread_t thread);
//send a cancellation request to specilized thread process
参数:要取消的线程ID
成功返回0,失败返回错误码。
取消和终止的对比
"取消"本质是一种请求而"终止"则是指令。
| 对比维度 | 自然终止 (return) | 主动终止 (pthread_exit) | 被动终止 (pthread_cancel) |
|---|---|---|---|
| 触发者 | 当前线程 | 当前线程 | 其他线程 |
| 响应时间 | 立即 | 立即 | 取决于取消状态(可能延迟) |
| 返回值 | 自定义 | 自定义 | 固定 为 PTHREAD_CANCELED |
| 清理函数 | 栈自动展开,执行析构 | 执行 pthread_cleanup_push |
执行 pthread_cleanup_push |
| 资源回收 | 可 join 或自动回收 |
可 join 或自动回收 |
可 join 或自动回收 |
| 是否可被拦截 | 不可以(除非你自己写 return 前的逻辑) |
不可以(线程自己决定退出) | 可以(目标线程可通过设置取消状态拒绝) |
主线程与新线程的分离
由于主线程常常需要等待接受新线程,这就占用了主线程资源。(新线程状态joinable)因此要线程分离(!joinable or detach)
cpp
pthread_detach(pthread_t thread);
可配合pthread_t pthread_self(); // 获取当前线程的ID
线程底层
线程创建的底层本质就是调用了clone(),而使得线程拥有独立的栈,线程间可以直接访问各栈。
| 对比维度 | pthread_create() (创建线程) | fork() (创建进程) |
| 核心系统调用 | clone() | clone() |
| 关键 flags 标志 | CLONE_VM (共享内存空间) CLONE_FILES (共享文件描述符表) CLONE_FS (共享文件系统信息) CLONE_SIGHAND (共享信号处理函数表) CLONE_THREAD(加入同一线程组) | flags 中没有设置 CLONE_VM、CLONE_FILES、CLONE_FS 等共享标志 |
| 共享资源 | 与父进程共享虚拟内存地址空间、文件描述符、信号处理器等 | 资源隔离,仅继承父进程数据的一份拷贝 |
| 调度单位 | 线程,拥有独立的 TID ,但同属一个线程组,共享一个 TGID(即进程 ID) |
进程,拥有独立的 PID |
|---|
☆线程的逻辑图解

☆轻量级进程的图解

感谢支持,持续更新
欢迎关注
