一、 Linux 线程简介
一、什么是线程(Thread)?
线程 是 进程内的一个轻量级执行单元。
一个进程中可以有多个线程,并且这些线程共享进程的大部分资源。
二、线程 vs 进程 对比
特性 | 进程(Process) | 线程(Thread) |
---|---|---|
地址空间 | 独立 | 共享(代码段、数据段、堆等) |
资源(文件描述符等) | 独立 | 共享 |
栈空间 | 各有独立栈 | 每个线程有独立栈 |
通信效率 | 进程间通信较复杂 | 线程间通信简单(共享内存) |
切换开销 | 大(涉及内核资源切换) | 小(不涉及页表切换等) |
使用场景 | 稳定、安全(如守护进程) | 高并发、高性能场景(如 Web 服务器) |
三、线程的优缺点
优点
创建、销毁、切换效率高
占用资源少
线程间通信方便(共享数据)
⚠️ 缺点
多线程共享数据,易引发同步问题/竞态条件
错误容易影响整个进程
二、线程创建
1、 线程控制
2、 线程创建:pthread_create
函数原型
#include <pthread.h>
int pthread_create(
pthread_t *thread, // 线程ID指针
const pthread_attr_t *attr, // 线程属性,默认传 NULL
void *(*start_routine)(void *), // 线程函数指针
void *arg // 线程函数参数
);
返回值:
值 | 含义 |
---|---|
0 |
成功 |
非 0 |
失败,返回错误码 |
pthread_t 定义
typedef unsigned long int pthread_t; // 实质上是无符号长整型
使用说明:
start_routine
为线程入口函数,格式统一为:void *thread_func(void *arg);
参数可以通过结构体传入,返回值也可以是结构体指针。
若不需参数或返回值,可传
NULL
和返回NULL
。
程序运行逻辑
主线程中,创建两个线程:
input_thread
:监听标准输入,写入共享缓冲区。output_thread
:读取共享缓冲区,打印到标准输出。
使用
pthread_join
等待两个线程完成(但由于是无限循环,这里只是保持主线程不退出)。
三、线程终止
线程终止的方式
线程可以通过以下几种方式终止:
方式 | 说明 |
---|---|
return |
在线程函数内直接返回,相当于 pthread_exit(NULL) |
pthread_exit |
在线程函数中调用,主动退出线程 |
pthread_cancel |
由其他线程发起,异步请求取消 |
线程终止后资源是否自动回收? 默认不会,需 pthread_join 或 pthread_detach 处理 |
函数详解
1)pthread_exit
#include <pthread.h>
void pthread_exit(void *retval);
结束调用该函数的线程。
可向其他线程返回数据
retval
。注意:retval 不要指向局部变量(函数栈帧会被销毁)。
推荐 使用
malloc
分配返回内容,在pthread_join
后回收。
2)pthread_join
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
等待指定线程终止,获取其返回值并回收资源。
用于阻塞等待线程结束,类似于进程中的
waitpid()
。retval
可以为NULL
,如果你不关心线程返回值。成功返回
0
,失败返回错误码。
3)pthread_detach
#include <pthread.h>
int pthread_detach(pthread_t thread);
将线程设置为 detached(分离)状态:
- 线程退出时,其资源自动释放,不再需要
pthread_join
。
- 线程退出时,其资源自动释放,不再需要
适用于主线程不关心子线程退出状态的场景。
与
pthread_join
互斥,不能对同一线程调用两者。
4)pthread_cancel
#include <pthread.h>
int pthread_cancel(pthread_t thread);
向目标线程发送 取消请求(并非强制终止)。
实际是否终止取决于:
取消状态:enable / disable
取消类型:deferred / asynchronous
线程默认:
状态:
enable
类型:
deferred
被取消线程必须在“取消点函数”中才会响应(如
read
,sleep
,pthread_join
等)。
如果线程成功被取消,pthread_join
获取到的返回值为:
retval == PTHREAD_CANCELED
5)pthread_setcancelstate
#include <pthread.h>
int pthread_setcancelstate(int state, int *oldstate);
- 设置当前线程是否 允许被取消。
宏定义 | 含义 |
---|---|
PTHREAD_CANCEL_ENABLE |
允许(默认) |
PTHREAD_CANCEL_DISABLE |
禁止被取消 |
oldstate
可为NULL
,也可保存原状态。
6)pthread_setcanceltype
#include <pthread.h>
int pthread_setcanceltype(int type, int *oldtype);
- 设置当前线程的 取消类型。
宏定义 | 含义 |
---|---|
PTHREAD_CANCEL_DEFERRED |
延迟取消(默认) |
PTHREAD_CANCEL_ASYNCHRONOUS |
异步取消(不建议轻易使用) |
小结对比表
方法 | 用途 | 是否释放资源 | 获取返回值 | 场景 |
---|---|---|---|---|
pthread_exit |
线程主动退出 | ❌(需 join 或 detach) | ✅ | 返回数据 |
return |
简化版 exit | ❌ | ✅ | 简单返回 |
pthread_join |
等待并获取返回值 | ✅ | ✅ | 主线程等子线程 |
pthread_detach |
自动资源释放 | ✅ | ❌ | 不关心返回值 |
pthread_cancel |
异步取消线程 | ❌(需 join 回收) | ✅(可得 CANCELED) | 主动终止 |