线程控制(创建、终止、等待、分离)
目录
1.前言
2.创建线程
pthread_create函数
3.线程终止
pthread_exit函数
pthread_cancel函数
4.线程等待
5.线程分离
1.前言
在Linux系统中,并不存在真正的线程,只有轻量级进程。所以,Linux系统只提供了操作轻量级进程的系统调用接口,并不提供直接操作线程的系统调用接口。但是,对于用户来说,用户想要对线程进行操作,只认线程相关的接口。于是,有人对轻量级进程的系统调用接口进行封装,转换成线程相关的接口语义给用户使用。
封装其实就是封装成库,这个库被叫做Linux的原生线程库:

- 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”开头。
- 要使用这些函数库,要通过引入头文<pthread.h>。
- 链接这些线程函数库时要使用编译器命令的“-lpthread”选项
2.创建线程
pthread_create函数
pthread库中创建线程的函数为pthread_create,创建出的新线程和主线程谁先运行时不确定的,由调度器说了算。
功能:用于创建一个新的线程。
函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void*), void *arg);
参数:
pthread_t *thread:这是一个输出型参数,用于存储新线程的标识符(线程ID)。线程创建成功后,系统会将线程ID写入该指针指向的内存。原生线程库中还提供了一个让线程获取自己的线程id的方法:pthread_t pthread_self(void)
const pthread_attr_t *attr:指向线程属性的指针,用于设置线程的属性(如栈大小、调度策略等),如果为NULL,则使用默认属性。
void *(*start_routine) (void *):
线程启动后执行的函数指针。该函数必须返回
void *并接受一个void *类型的参数。线程从该函数的起始处开始执行,函数返回时线程终止。
void *arg:传递给start_routine函数的参数。如果需要传递多个参数,可以将它们封装在一个结构体中,然后传递结构体的指针。返回值:
成功:返回
0。失败:返回错误码(非零值),常见的错误码包括:
EAGAIN:系统资源不足,无法创建线程。
EINVAL:线程属性无效。
EPERM:没有权限设置调度策略或参数。
使用示例:
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;void* handler(void* arg)
{int cnt = 5;while(cnt--){cout << "I am a thread" << endl;sleep(1);}return nullptr;
}int main()
{pthread_t thread_id = 0;int ret = pthread_create(&thread_id, NULL, handler, NULL);if(ret != 0){cout << "create error" << endl;}sleep(6);return 0;
}
运行结果:

当我们的代码创建出一个线程之后,新线程就会和主线程并发执行自己的代码。如果主线程先退,表示进程退出,新线程也会结束,如果新线程先结束,主线程不会直接结束,会等自己的代码运行完之后再结束。
3.线程终止
终止一个线程的方法有三种:
- return:使用return语句退出。
- pthread_exit:线程可以调用pthread_exit函数终止自己。
- pthread_cancel:一个线程可以调用pthread_cancel终止同一进程中的另一个线程。
pthread_exit函数
功能:终止当前进程的执行。
函数原型:void pthread_exit(void *retval)
参数:
void *retval:
线程的返回值,通常是一个指向某个数据的指针。
如果不需要返回值,可以传递
NULL。该返回值可以被其他线程通过
pthread_join获取。返回值:该函数没有返回值。
需要注意:pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时,线程函数已经退出了。
使用示例:
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;void* handler(void* arg)
{int cnt = 3;while(cnt--){cout << "I am a thread" << endl;sleep(1);if(cnt == 1){cout << "called pthead_exit" << endl;pthread_exit(NULL);}}return nullptr;
}int main()
{pthread_t thread_id = 0;int ret = pthread_create(&thread_id, NULL, handler, NULL);if(ret != 0){cout << "create error" << endl;}sleep(5);return 0;
}
运行结果:

pthread_cancel函数
功能:用于请求取消(终止)指定的线程。
函数原型:int pthread_cancel(pthread_t thread)
参数:
pthread_t thread:目标线程的标识符(线程ID),即需要取消的线程。返回值:
成功:返回
0。失败:返回错误码(非零值)。
使用示例:
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;void* handler(void* arg)
{int cnt = 10;while(cnt--){cout << "new thread say: I am runnig" << endl;sleep(1);}return nullptr;
}int main()
{pthread_t tid = 0;int ret = pthread_create(&tid, NULL, handler, NULL);if(ret != 0){cout << "create thread error" << endl;}cout << "create thread success" << endl;sleep(5);ret = pthread_cancel(tid);if(ret != 0){cout << "cancel thread error" << endl;}cout << "cancel thread success" << endl;return 0;
}
运行结果:

4.线程等待
在进程控制中,如果一个子进程退出,父进程需要对子进程进行回收,也就是需要进行进程等待,不然就会造成僵尸进程而引发资源泄漏问题;在线程这里,一个线程退出后,主线程需要对其进行回收,不然也会产生类似的问题。
- 已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。
- 创建新的线程不会复用刚才退出线程的地址空间。
pthread_join函数
功能:用于等待指定的线程终止,并获取该线程的返回值。
函数原型:int pthread_join(pthread_t thread, void **value_ptr)
参数:
thread: 要等待的线程的标识符(pthread_t类型)。
value_ptr: 指向一个指针的指针,用于存储目标线程的返回值。如果不需要返回值,可以设置为NULL。返回值:
成功时返回
0。失败时返回一个错误码(非零值),常见的错误码包括:
ESRCH: 没有找到与指定线程 ID 对应的线程。
EINVAL: 线程是分离的(detached)或者已经有其他线程在等待它。
EDEADLK: 检测到死锁(例如,线程试图等待自己)。需要注意:
调用该函数的线程将挂起等待,直到id为thread的线程终止。
thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:
- 1. 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值。
- 2. 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数 —— PTHREAD_ CANCELED。
- 3. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。
- 4. 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数。
使用示例:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>void* thread_function(void* arg) {int* value = (int*)arg;printf("Thread is running with value: %d\n", *value);int* result = (int*)malloc(sizeof(int));*result = *value * 2;pthread_exit(result);
}int main() {pthread_t thread;int value = 10;int* retval;if (pthread_create(&thread, NULL, thread_function, &value) != 0) {perror("pthread_create");exit(EXIT_FAILURE);}if (pthread_join(thread, (void**)&retval) != 0) {perror("pthread_join");exit(EXIT_FAILURE);}printf("Thread returned: %d\n", *retval);free(retval);return 0;
}
运行结果:

5.线程分离
默认情况下,新创建的线程是需要等待的,新线程退出后,需要主线程对其进行pthread_join操作,否则无法释放资源,从而造成系统资源泄漏。如果不关心线程的返回值,等待就是一种负担,这个时候,我们可以将该线程分离,当线程退出时,操作系统会自动释放被分离的线程的资源。
注意:线程分离只是主线程不用等待新线程的退出了,并不是把新线程剥离下来了。
pthread_detach函数
功能:用于将指定的线程标记为“分离状态”,分离状态的线程在终止时会自动释放其资源,而不需要其他线程调用
pthread_join来回收资源。函数原型:int pthread_detach(pthread_t thread)
参数:
thread:要分离的线程的标识符(pthread_t类型)返回值:
成功时返回
0。失败时返回一个错误码(非零值),常见的错误码包括:
ESRCH: 没有找到与指定线程 ID 对应的线程。
EINVAL: 线程已经是分离状态,或者线程已经终止。注意:
- 一旦线程被分离,就不能再调用
pthread_join来等待它,否则会导致未定义行为- 线程分离,可以是线程组内其他线程对目标线程进行分离,也可以是线程自己将自己分离。
使用示例:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void* thread_function(void* arg) {int* value = (int*)arg;printf("Thread is running with value: %d\n", *value);sleep(2); // 模拟线程执行一些任务printf("Thread is exiting\n");pthread_exit(NULL);
}int main() {pthread_t thread;int value = 10;if (pthread_create(&thread, NULL, thread_function, &value) != 0) {perror("pthread_create");exit(EXIT_FAILURE);}// 分离线程if (pthread_detach(thread) != 0) {perror("pthread_detach");exit(EXIT_FAILURE);}printf("Main thread continues to run...\n");sleep(3); // 确保分离的线程有足够时间完成return 0;
}
运行结果:

相关文章:
线程控制(创建、终止、等待、分离)
目录 1.前言 2.创建线程 pthread_create函数 3.线程终止 pthread_exit函数 pthread_cancel函数 4.线程等待 5.线程分离 1.前言 在Linux系统中,并不存在真正的线程,只有轻量级进程。所以,Linux系统只提供了操作轻量级进程的系统调用…...
【备份】php项目处理跨域请求踩坑
这都是老生常谈的东西了。我还在踩坑,记录一下。 我在项目入口明明写了如下代码: // 处理预检请求 (OPTIONS) if ($_SERVER[REQUEST_METHOD] OPTIONS) {header("Access-Control-Allow-Origin: https://xxx.vip");header("Access-Cont…...
目标检测YOLO实战应用案例100讲-面向无人机图像的小目标检测
目录 知识储备 YOLO v8无人机拍摄视角小目标检测 数据集结构 环境部署说明 安装依赖 模型训练权重和指标可视化展示 训练 YOLOv8 PyQt5 GUI 开发 主窗口代码 main_window.py 使用说明 无人机目标跟踪 一、目标跟踪的基本原理 二、常用的目标跟踪算法 基于YOLOv…...
实现 Leaflet 多类型点位标记与聚合功能的实战经验分享
在现代的地理信息系统(GIS)应用中,地图功能是不可或缺的一部分。无论是展示商业网点、旅游景点还是公共服务设施,地图都能以直观的方式呈现数据。然而,当数据量较大时,地图上可能会出现大量的标记点&#x…...
Linux 环境“从零”部署 MongoDB 6.0:mongosh 安装与数据操作全攻略
前提 完成linux平台部署MongoDB【部署教程】且完成mongosh的安装 由于本人使用的是6.0版本的MongoDB,新版本 MongoDB(尤其是 6.0 及以上版本)已经不再默认捆绑传统的 mongo shell,而改用新的 MongoDB Shell(mongosh&am…...
深度学习五大模型:CNN、Transformer、BERT、RNN、GAN详细解析
# 深度学习五虎将:当CNN遇见Transformer的奇幻漂流 ## 序章:AI江湖的兵器谱排行 2012年,多伦多大学的厨房里,Hinton的学生们用GPU煎了个"AlexNet"荷包蛋,从此开启了深度学习的热兵器时代。如今五大模型各显…...
004 rocketmq集群
1、集群模式 在RocketMQ中,集群的部署模式是比较多的,有以下几种: public class ConsumerDemo {public static void main(String[] args) throws Exception {DefaultMQPushConsumer consumer new DefaultMQPushConsumer("test-group&qu…...
基于 Python 深度学习的电影评论情感分析可视化系统(2.0 全新升级)
基于 Python 深度学习的电影评论情感分析可视化系统,基于 Flask 深度学习,构建了一个 影评情感分析系统,能够 自动分析影评、计算情感趋势 并 可视化展示,对于电影行业具有重要参考价值! 基于 Python 深度学习的电影评…...
Linux内核配置与构建原理
Kconfig文件 Kconfig是Linux内核中用于配置功能的脚本语言系统,由众多内核源码树中每个目录下的Kconfig文件组成。它定义Linux相关的配置选项层次结构和依赖关系。 menuconfig工具,会抓取Kconfig中的信息,为用户输出友好的交互式菜单选项配…...
大语言模型微调的基本概念介绍
大型语言模型(LLMs)正在以惊人的速度发展,LLM微调的潜力更是如此。大型语言模型的生命周期有几个关键步骤,今天我们将要介绍这个周期中最丰富、最耗时的一部分——LLM微调过程。 大语言模型的生命周期 在深入了解大型语言模型&a…...
实例分割 | yolov11训练自己的数据集
前言 因工作要求使用的都是yolov5系列的模型,今天学习一下最先进的yolov11,记录一下环境配置及训练过程。 1.项目下载及环境安装 源码位置:yolov11 可以看到,这里要求python版本大于等于3.8,我这里安装python3.10.…...
vue3:四嵌套路由的实现
一、前言 1、嵌套路由的含义 嵌套路由的核心思想是:在某个路由的组件内部,可以定义子路由,这些子路由会渲染在父路由组件的特定位置(通常是 <router-view> 标签所在的位置)。通过嵌套路由,你可以实…...
AIGC和搜索引擎的异同
AIGC(生成式人工智能)与搜索引擎的核心差异体现在信息处理方式和输出形态上,我们可以从以下维度对比: 一、工作原理的本质差异 信息检索机制 搜索引擎:基于关键词匹配(如"中暑怎么办"→返回相关…...
ES批量查询
在 Elasticsearch 中,multi_search(也称为 msearch)是一种允许你在单个请求中执行多个搜索操作的 API。它可以显著减少网络开销,尤其是在需要执行多个查询时。multi_search 会将多个查询打包成一个请求发送给 Elasticsearch&#…...
Vue2学习
一、Vue3 基础 监视属性 天气案例 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>天气案例</…...
PySide(PyQT)重新定义contextMenuEvent()实现鼠标右键弹出菜单
在 PySide中,contextMenuEvent() 是 QWidget 类(以及继承自它的所有子类)的一个事件处理方法,主要用于处理上下文菜单事件,也就是当用户在控件上右键点击时触发的事件。 • 通过重新定义contextMenuEvent()来实现自定…...
Storm实时流式计算系统(全解)——下
storm编程案例-网站访问来源实时统计-需求 storm编程-网站访问来源实时统计-代码实现 根据以上条件可以只写一个类,我们只需要写2个方法和一个main(),一个读取/发射(spout)。 一个拿到数据统计后发到redis…...
配置Nginx日志url encode问题
文章目录 配置Nginx日志url encode问题方法1-lua方法2-set-misc-nginx-module 配置Nginx日志url encode问题 问题描述: 当自定义日志输出格式,需要输出http请求中url参数时,如果参数中包含中文,是会进行url encode的,…...
JAVA SE 包装类和泛型
文章目录 📕1. 包装类✏️1.1 基本数据类型和对应的包装类✏️1.2 装箱和拆箱✏️1.3 自动装箱和自动拆箱 📕2. 泛型✏️2.1 泛型的语法✏️2.2 泛型类的使用✏️2.3 裸类型(Raw Type)✏️2.4 擦除机制✏️2.5 泛型的上界✏️2.6 泛型方法✏️2.7 通配符…...
基于Linux系统的物联网智能终端
背景 产品研发和项目研发有什么区别?一个令人发指的问题,刚开始工作时项目开发居多,认为项目开发和产品开发区别不大,待后来随着自身能力的提升,逐步感到要开发一个好产品还是比较难的,我认为项目开发的目的…...
GitHub 被黑或因员工安装 Nx Console 恶意扩展引发,更多详情待调查
聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士专栏供应链安全数字化时代,软件无处不在。软件如同社会中的“虚拟人”,已经成为支撑社会正常运转的最基本元素之一,软件的安全性问题也正在成为当今社会的…...
软考高项案例分析8:项目风险管理
软考高项案例分析8:项目风险管理 一、项目风险管理过程 1、规划风险管理; 2、识别风险; 3、实施定性风险分析; 4、实施定量风险分析; 5、规划风险应对; 6、实施风险应对; 7、监督风险; 二、案例分析知识点 1. 风险应对措施 威胁应对策略:上报、规避、转移、…...
《科技代替了我工作》的传播入口:技术焦虑如何落到听众
从内容传播角度看,《科技代替了我工作》有天然的现实入口,但写法必须克制。它不是技术教程,也不是政策评论,而是把技术变化落到一个普通人的饭碗、身份感和安全感上。这个标题容易被记住,因为它把宏大的技术词变成了第…...
知识竞赛实时排名:平分怎么处理?
知识竞赛实时排名算法:平分怎么处理?公平 精准 高效 让每一分都经得起推敲🎯 一、平分问题的核心挑战在知识竞赛中,当多位选手或队伍总分相同时,如何公平、高效地确定实时排名,是组织者面临的关键技术难…...
rebar3最佳实践清单:避免常见陷阱的20个专业建议
rebar3最佳实践清单:避免常见陷阱的20个专业建议 【免费下载链接】rebar3 Erlang build tool that makes it easy to compile and test Erlang applications and releases. 项目地址: https://gitcode.com/gh_mirrors/re/rebar3 rebar3是Erlang生态系统中最流…...
EASY-HWID-SPOOFER:Windows硬件指纹保护终极方案
EASY-HWID-SPOOFER:Windows硬件指纹保护终极方案 【免费下载链接】EASY-HWID-SPOOFER 基于内核模式的硬件信息欺骗工具 项目地址: https://gitcode.com/gh_mirrors/ea/EASY-HWID-SPOOFER 在数字时代,您的电脑硬件信息正在被悄无声息地追踪。无论是…...
毕业设计精选【芳心科技】无人机定点投放控制
实物效果图:实现功能:本次设计的目的是实现无人机在空中投放物品的落点计算,系统的核心是单片机,它控制本系统的各种功能,所以它的选择是非常重要的,在本设计中选用的是GD32F103C8T6单片机,这款…...
大牛直播SDK(SmartMediaKit)Windows平台RTSP/RTMP直播播放SDK集成说明(C#版)
文档概述 本文介绍大牛直播SDK(SmartMediaKit)在 Windows 平台下 RTSP、RTMP 直播播放模块的集成方法,面向 Windows Forms、WPF 等 C# 客户端应用场景,重点说明 SDK 集成准备、播放器初始化、RTSP/RTMP 播放、播放参数配置、事件…...
超自动化运维,您需要的是“可信执行平台(TEP)”
在AI智能体与自动化工具蓬勃发展的今天,各类开源框架与轻量工具层出不穷。它们让“用自然语言驱动电脑做事”的愿景触手可及——文件操作、脚本执行、浏览器控制,一切看似高效便捷。然而,当我们将视线从个人桌面转向企业的数据中心、核心生产…...
从济南话到烟台腔:ElevenLabs山东话语音泛化能力极限测试(覆盖17地市、1362条测试句、WER 8.7%实测数据)
更多请点击: https://codechina.net 第一章:从济南话到烟台腔:ElevenLabs山东话语音泛化能力极限测试(覆盖17地市、1362条测试句、WER 8.7%实测数据) 为验证ElevenLabs语音合成模型对山东方言的跨地域泛化能力&#x…...
