线程学习笔记整理
一、线程概论
基本概念
-
Linux中线程是轻量级的进程,线程属于某个进程
-
作用:实现并发,处理相对耗时任务
线程特征
-
进程是系统中最小的资源分配单位
-
线程是系统中最小的执行单位
-
线程关系:进程中,线程与线程是平级关系
-
主线程:进程中默认有一个主线程
二、线程与进程的区别
| 对比项 | 进程 | 线程 |
|---|---|---|
| 资源共享 | 资源对立,独立地址空间 | 资源共享,共享进程地址空间 |
| 栈区 | 独立 | 有各自独立的栈区(默认8MB) |
| 稳定性 | 相对稳定 | 不稳定(一个线程崩溃会导致整个进程崩溃) |
| 创建开销 | 大(需要创建3GB空间) | 小(只需在进程空间中开辟新栈区) |
| 并发度 | 较低 | 较高 |
| 通信方式 | 复杂(管道、消息队列等) | 简单(共享内存) |
三、线程编程步骤(POSIX)
- 创建多线程 → 2. 线程空间操作 → 3. 线程资源回收
四、查看线程信息命令
# 查看线程信息
ps -eLo pid,ppid,lwp,stat,comm
ps -eLf
# 参数说明:
# pid: 进程ID
# ppid: 父进程ID
# lwp: 轻量级进程ID(线程ID)
# stat: 状态
# comm: 命令名
五、线程相关函数
1. 创建线程
#include <pthread.h>
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);
功能:创建指定线程
参数:
-
thread:线程ID(输出参数) -
attr:线程属性(通常NULL,使用默认属性) -
start_routine:线程回调函数(线程执行入口) -
arg:传递给回调函数的参数
返回值:
-
成功:0
-
失败:错误码
示例:
void *thread_func(void *arg) {
// 线程执行代码
return NULL;
}
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
2. 获取线程ID
pthread_t pthread_self(void);
功能:获取当前线程ID
返回值 :当前线程ID(unsigned long int,使用%lu格式打印)
示例:
printf("Thread ID: %lu\n", pthread_self());
3. 线程退出
方式一:线程自行退出
void pthread_exit(void *retval);
功能:子线程自行退出
参数 :retval - 线程退出时的返回值("临死遗言")
示例:
void *thread_func(void *arg) {
// ... 执行代码
pthread_exit((void *)"Thread finished");
}
方式二:请求结束线程
int pthread_cancel(pthread_t thread);
功能:请求结束一个线程
参数 :thread - 要结束的线程ID
返回值:
-
成功:0
-
失败:非0值
4. 线程资源回收(阻塞方式)
int pthread_join(pthread_t thread, void **retval);
功能:
-
回收指定线程资源
-
具有阻塞等待功能(如果线程未结束,会阻塞)
参数:
-
thread:要回收的子线程ID -
retval:接收子线程返回值(pthread_exit的值)
返回值:
-
成功:0
-
失败:非0值
示例:
void *retval;
pthread_join(tid, &retval);
printf("Thread returned: %s\n", (char *)retval);
5. 线程分离属性
int pthread_detach(pthread_t thread);
功能:设置线程分离属性
参数:线程ID(通常填自己的ID)
返回值:
-
成功:0
-
失败:非0值
特点:
-
分离的线程退出后,系统自动回收资源(栈区)
-
分离后,创建者不能再使用
pthread_join回收
六、注意事项
-
线程安全:
-
多个线程访问共享资源需要同步(互斥锁、信号量等)
-
避免竞争条件
-
-
内存管理:
-
线程共享进程的堆空间
-
每个线程有独立的栈空间
-
传递动态分配的内存要注意释放
-
-
编译选项:
gcc -pthread program.c -o program -
错误处理:
-
所有pthread函数返回0表示成功
-
非0值为错误码,使用
strerror(errno)查看错误信息
-
八、线程状态
线程可以处于以下状态:
-
就绪:等待CPU调度
-
运行:正在执行
-
阻塞:等待某个事件(如I/O、锁)
-
终止:执行完成
九、线程使用场景
-
I/O密集型任务:一个线程阻塞时,其他线程可继续执行
-
并行计算:将大任务分解为多个子任务
-
服务器编程:每个连接一个线程
-
GUI应用:主线程处理界面,工作线程处理耗时操作