当前位置: 首页 > news >正文

C++线程详解

1.Linux线程的概念

我们在写C/C++程序的时候,都是重main函数开始执行的,从上而下,只有一条执行路线。如果我们想要同时干两件事或者多件事,这次我们就需要线程,分出一个执行分支来执行任务。

•在一个程序里的一个执行路线叫做线程

•线程在进程内部运⾏,本质是在进程地址空间内运行

•有些任务场景需要 “等待 IO”, 为了让等待 IO 的时间能够去做⼀些其他的工作, 也需要用到并发编程。其次,虽然多进程也能实现 并发编程, 但是线程比进程更轻量.

2.创建线程

在Linux上,没有提供专门的线程,而是提供了轻量化进程,为了满足用户的遍历,在语言层实现了封装,在pthread的库中提供了专门的调用接口。

2-1 认识pthread_create函数

#include <pthread.h>int pthread_create(pthread_t *thread,          // 指向线程标识符的指针const pthread_attr_t *attr, // 线程属性(通常设为 NULL 使用默认属性)void *(*start_routine)(void*), // 线程执行的函数void *arg                   // 传递给线程函数的参数
);

参数说明

  1. thread
    指向 pthread_t 类型的变量,用于存储新创建线程的标识符。

  2. attr
    指向 pthread_attr_t 类型的结构体,用于设置线程的属性(如栈大小、调度策略等)。若为 NULL,则使用默认属性。

  3. start_routine
    线程启动后要执行的函数,必须符合 void* (*)(void*) 的函数签名,即接受一个 void* 类型的参数并返回 void*

  4. arg
    传递给 start_routine 的参数,类型为 void*。若无需传递参数,可设为 NULL

返回值

  • 成功:返回 0
  • 失败:返回错误码(如 EAGAINEINVAL 等),且 *thread 的值未定义。

2-2 案例实现

//新线程执行流
void* threadrun(void* args)
{//这里的args拿到的就是创建线程时传递的地址,类型是无符号类型,在使用时需要自己进行强转std::string name = (const char*)args;while(1){std::cout << "我是新线程:name" << name << std::endl;sleep(1);}return nullptr;
}//main执行流
int main()
{pthread_t tid;//调用接口创建线程pthread_create(&tid, nullptr, threadrun, (void*)"thread -1");while(1){std::cout << "我是主线程..." << std::endl;sleep(1);}return 0;}//运行结果
我是主线程...
我是新线程:namethread -1
我是主线程...
我是新线程:namethread -1
我是主线程...
我是新线程:namethread -1
我是主线程...
我是新线程:namethread -1

可以看到上述有两个while死循环,分别属于两个执行流,同时进行输出。

3.线程等待

主线程也就是main执行流有时需要等待新线程完成相应的任务,并回收新线程的资源。这个时候就需要线程等待(类似于进程等待)

3-1 线程等待函数

#include <pthread.h>int pthread_join(pthread_t thread, void **retval);
  • 功能:阻塞当前线程,直到指定的 thread 线程终止。
  • 参数
    • thread:目标线程的标识符(由 pthread_create() 返回)。
    • retval:指向 void* 的指针,用于存储线程函数的返回值(即 start_routine 的返回值)。若无需获取返回值,可设为 NULL
  • 返回值
    • 成功:返回 0
    • 失败:返回错误码(如 EDEADLKESRCH 等)。

3-2 实现案例

void* routine(void* args)
{std::string name = (char*)args;int cut = 5;while(cut--){sleep(1);std::cout << "我是一个线程" << Formata(pthread_self()) << cut << std::endl;}static int a = 10;return (void*)(&a);
}//实现一个线程等待的案例
int main()
{pthread_t tid;int n = pthread_create(&tid, nullptr, routine, (void*)"thread -1");void* a = nullptr;pthread_join(tid,&a);std::cout << *(int*)a << std::endl;}

这里的新线程在内部创建了一个静态变量a,并返回了a的地址。主线程(main)进行线程等待,回收新线程。拿到返回值a的地址。

4. 线程分离

在新线程结束的时候,我们需要等待主线程回收新线程,如果我们不想等待新线程,我们可以把新线程分离出来,这样在其终止后,资源会自动释放,无需其他线程等待。

4-1线程分离函数

#include <pthread.h>int pthread_detach(pthread_t thread);
  • 功能:将线程标记为 “分离” 状态,使其终止后资源自动释放,无需其他线程调用 pthread_join()
  • 参数
    • thread:目标线程的标识符。
  • 返回值
    • 成功:返回 0
    • 失败:返回错误码(如 ESRCH)。

4-2 实现案例

主线程和新线程都可以设置线程分离

void* thread(void* args)
{// pthread_detach(pthread_self());sleep(10);}int main()
{pthread_t tid;pthread_create(&tid, nullptr, thread, (void*)"threadtest");pthread_detach(tid);while(1){std::cout << "我是主线程" << std::endl;}
}

5.线程退出

#include <pthread.h>
void pthread_exit(void *retval);
  • 功能:立即终止当前线程,并通过 retval 传递返回值。

http://www.dtcms.com/a/306557.html

相关文章:

  • 关于“LoggerFactory is not a Logback LoggerContext but Logback is on ......“的解决方案
  • [源力觉醒 创作者计划]_巅峰对话:文心 vs. DeepSeek/Qwen 3.0 深度解析
  • Wan2.2 - 阿里最新开源视频生成模型 支持文生视频/图生视频 支持50系显卡 一键整合包
  • 293F细胞是什么?
  • C语言《智能自平衡小车,实现平衡功能的基础上,加入了超声波避障、超声波跟随、蓝牙遥控等功能》+源代码+文档说明
  • DEC 指令
  • spark的broadcast variables
  • 重庆邮电大学2026年计算机/软件/人工智能/网安考研备考指南
  • css初学者第二天
  • RabbitMQ 发送方确认的两大工具 (With Spring Boot)
  • 15、点云<—>深度图转换原理
  • Centos 7.9安装部署cobbler-自动化部署服务器完整教程
  • 【Flask 基础 ①】 | 路由、参数与模板渲染
  • 【AI】开源项目整理
  • 数据库账号密码、查找文件、文件权限
  • Python 程序设计讲义(45):组合数据类型——集合类型:集合的常用操作
  • TCP面试
  • Mint聊天室 · 猫猫狐狐的QA夜会· Vol.01
  • 智慧界桩:湿地与地质公园的生态链守护者
  • 【数据结构初阶】--二叉树(五)
  • 模板初阶
  • C++ 中 NULL 与 nullptr 有什么区别?
  • Redis 中 key 的过期策略 和 定时器的两种实现方式
  • 基于逻辑回归、随机森林、梯度提升树、XGBoost的广告点击预测模型的研究实现
  • 超宽带测距+测角+无线通信一体化跟随模组:机械狗、无人车、无人机等跟随
  • Dify-15: 开发指南
  • DIY循迹模块多路改造指南
  • 【WRF-Chem第三期】输入数据概览
  • 随笔之TDengine基准测试示例
  • LeetCode 25:K 个一组翻转链表