线程之多线程函数
进程是操作系统分配的最小单位,而线程是进程内部的执行单元,是操作系统CPU调度的最小单位,简单来说就是一个进程可以有多个线程。(默认,延时取消):线程不会立刻终止,直到下一个取消点(Cancellation Point)才响应。将线程设置为分离态,分离态下线程退出后系统自动回收其资源,无需调用pthread_join。ps:销毁后的属性可以重新初始化,不影响已创建的线程。(异步取消):线程收到请求
一,线程的概念
进程是操作系统分配的最小单位,而线程是进程内部的执行单元,是操作系统CPU调度的最小单位,简单来说就是一个进程可以有多个线程。
二,与进程对比
| 维度 | 进程 | 线程 |
|---|---|---|
| 资源 | 独立的地址空间、文件描述符等系统资源 | 共享所属进程的地址空间和资源 |
| 调度 | 进程是资源分配的基本单位 | 线程是 CPU 调度的基本单位 |
| 开销 | 创建 / 切换开销大(需复制页表等) | 创建 / 切换开销小(共享资源,仅保存少量寄存器) |
| 通信 | 需通过 IPC(管道、消息队列、共享内存) | 可直接读写共享变量,通信简单但需同步 |
| 健壮性 | 进程崩溃不影响其他进程 | 一个线程崩溃会导致整个进程退出 |
应用场景:
- 进程适用于资源隔离要求高,稳定性优先的场景,如Web服务器的工作进程,数据库的多进程架构
- 线程适用于高并发,计算密集型任务,如Web服务器的线程池,GUI程序的后台任务处理
三,多线程相关函数
1.前置条件
- 头文件:
#include <pthread.h>
- 编译时必须加链接库参数:
gcc main.c -o main -lpthread
- 所有pthread函数成功返回0,失败返回错误码
2.创建线程:pthread_create
作用:创建一个新线程,让它开始指定的函数,参数结构如下:
int pthread_create(
pthread_t *thread, // 输出:存储新线程的ID
const pthread_attr_t *attr, // 线程属性(默认填NULL)
void *(*start_routine)(void *), // 线程要执行的函数指针,也称入口函数
void *arg // 传递给线程函数的参数(无参数填NULL)
);
3.等待线程结束:pthread_join
作用:阻塞等待指定线程执行完毕,并回收线程资源(避免内存泄漏),参数结构如下:
int pthread_join(
pthread_t thread, // 要等待的线程ID
void **retval // 接收线程的返回值(不接收填NULL)
);
4.线程主动退出:pthread_exit
线程自己调用,主动终止运行,可以带返回值,结构如下:
void pthread_exit(void *retval); // retval:线程返回值
ps:即使主线程退出,子线程也能继续执行
5.获取线程自身线程id:pthread_self
线程获取自己的id,类似于进程的getpid,结构如下:
pthread_t pthread_self(void);
线程属性相关函数
6.分离线程:pthread_detach
将线程设置为分离态,分离态下线程退出后系统自动回收其资源,无需调用pthread_join
结构如下:
int pthread_detach(pthread_t thread);
7.初始化线程属性:pthread_attr_init
初始化线程属性对象,将属性设置为默认值,结构如下:
int pthread_attr_init(pthread_attr_t *attr);//attr需要被初始化的线程属性对象
8.设置线程属性对象的分离状态:pthread_attr_setdetachstate
用于设置线程属性对象的分离状态,结构如下:
int pthread_attr_setdetachstate(
pthread_attr_t *attr, //设置分离状态的线程属性对象
int detachstate //用于指定线程的分离状态
//PTHREAD_CREATE_JOINABLE :表示将线程设置为结合态
//PTHREAD_CREATE_DETACHED :表示将线程设置为分离态
);
9.销毁线程属性:pthread_attr_destroy
销毁属性对象占用的资源,与初始化函数成对使用,结构如下:
int pthread_attr_destroy(pthread_attr_t *attr);
ps:销毁后的属性可以重新初始化,不影响已创建的线程。
线程取消相关函数
10.请求取消指定线程:pthread_cancel
向指定线程发送取消请求,它只是一个请求,调用成功也只是代表请求已提交,不代表线程已经终止了,结构如下:
int pthread_cancel(pthread_t thread);
11.设置取消状态:pthread_setcancelstate
设置调用线程自身的取消状态,即是否允许响应pthread_cancel的请求,参数:
| 参数 | 说明 |
|---|---|
state |
新的取消状态,二选一:
|
oldstate |
输出参数,存储修改前的旧状态(传NULL表示不需要保存旧状态) |
int pthread_setcancelstate(int state, int *oldstate);
12.设置取消类型:pthread_setcanceltype
设置调用线程自身的取消类型,仅在取消状态为PTHREAD_CANCEL_ENABLE时生效,决定线程收到请求后何时终止,参数:
| 参数 | 说明 |
|---|---|
type |
新的取消类型,二选一:
|
oldtype |
输出参数,存储修改前的旧类型(传NULL表示不需要保存旧类型) |
int pthread_setcanceltype(int type, int *oldtype);
13.取消函数的示例代码
//请求取消指定线程
/*
请求取消指定线程取决于线程的取消状态和取消类型
取消状态:可取消和不可取消
取消类型:延时取消和可被立即取消(异步取消)
三种情况:
1. 可取消的线程+延时取消
2. 可取消的线程+可被立即取消
3. 不可取消的线程
*/
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
//情况1:可取消的线程+延时取消
void *thread1(void *arg)
{
//设置线程1取消状态和取消类型
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
while(1) {
//结果:不会每隔1秒打印一次线程1正在运行...
//因为线程1收到请求取消信号,线程1会在取消点进行取消
printf("线程1正在运行...\n");
sleep(1);
}
return NULL;//注意:此处返回值不可以为丢,没有实际意义
}
//情况2:可取消的线程+可被立即取消
void *thread2(void *arg)
{
//设置线程2取消状态和取消类型
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
while(1) {
//因为设置为了立即取消,所以线程2会立即取消
//所以将sleep注释之后无法显示
printf("线程2正在运行...\n");
//sleep(1);
}
return NULL;//注意:此处返回值不可以为丢,没有实际意义
}
//情况3:不可取消的线程
void *thread3(void *arg)
{
//设置线程3取消状态为不可取消
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
while(1) {
//因为设置为了不可取消,所以线程3不会取消
printf("线程3正在运行...\n");
sleep(1);
}
return NULL;//注意:此处返回值不可以为丢,没有实际意义
}
int main(int argc,const char *argv[])
{
//情况1:可取消的线程+延时取消
pthread_t tid1 = 0;
int ret = pthread_create(&tid1,NULL,thread1,NULL);
if(ret != 0) {
fprintf(stderr,"创建线程1失败,错误信息:%s\n",strerror(ret));
return -1;
}
printf("创建线程1成功,线程1ID:%ld\n",tid1);
//情况2:可取消的线程+可被立即取消
pthread_t tid2 = 0;
int ret2 = pthread_create(&tid2,NULL,thread2,NULL);
if(ret2 != 0) {
fprintf(stderr,"创建线程2失败,错误信息:%s\n",strerror(ret2));
return -1;
}
printf("创建线程2成功,线程2ID:%ld\n",tid2);
//情况3:不可取消的线程
pthread_t tid3 = 0;
int ret3 = pthread_create(&tid3,NULL,thread3,NULL);
if(ret3 != 0) {
fprintf(stderr,"创建线程3失败,错误信息:%s\n",strerror(ret3));
return -1;
}
printf("创建线程3成功,线程3ID:%ld\n",tid3);
//请求取消指定的线程1
int ret_cancel = pthread_cancel(tid1);
//只能说明请求取消成功,不能说明会被立即取消
if(ret_cancel != 0) {
fprintf(stderr,"请求取消线程1失败,错误信息:%s\n",strerror(ret_cancel));
return -1;
}
printf("请求取消线程1成功\n");
//请求取消指定的线程2
int ret_cancel2 = pthread_cancel(tid2);
if(ret_cancel2 != 0) {
fprintf(stderr,"请求取消线程2失败,错误信息:%s\n",strerror(ret_cancel2));
return -1;
}
printf("请求取消线程2成功\n");
//请求取消指定的线程3
int ret_cancel3 = pthread_cancel(tid3);
if(ret_cancel3 != 0) {
fprintf(stderr,"请求取消线程3失败,错误信息:%s\n",strerror(ret_cancel3));
return -1;
}
printf("请求取消线程3成功\n");
//阻塞等待线程退出
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);
return 0;
}
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)