Linux应用层开发--线程
一、 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, // 线程属性,默认传 NULLvoid *(*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) | 主动终止 |