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

C/C++ 多线程[1]---线程创建+线程释放+实例

文章目录

  • 前言
  • 1. 多线程创建
  • 2. 多线程释放
  • 3. 实例
  • 总结

前言

说来惭愧,写了很久的代码,一个单线程通全部。可能是接触的项目少吧,很多多线程的概念其实都知道,但是实战并没有用上。前段时间给公司软件做一个进度条,涉及到多线程的操作,主要是不影响主线程UI卡死的问题。
这篇博客写一下多线程的一个demo


1. 多线程创建

创建多线程在C++11的标准下使用的是std::thread。

std::thread后面的参数有下面几种:
函数指针或可调用对象(Callable Object):这是新线程要执行的函数或函数对象。可以是函数指针、函数对象、lambda 表达式等。

传递给函数的参数:如果需要向线程函数传递参数,这些参数应该在创建线程时一并提供。

其他可选参数:一些可选参数可以通过第二个参数传递给std::thread构造函数,例如线程的启动参数等。

比如我下面这句话std::thread m_thOne = std::thread(&fun1);
创建一个名为m_thOne的线程,线程调用的是函数f1。这里第一个参数要传递函数的地址。

如果有一个函数void fun3(int a,string b);这个函数是类FUN的一个成员函数。

class FUN
{
public::void fun3(int a,string b){};
}

那么在main中我想开一个线程跑这个fun3函数,现有一个FUN的对象指针m_pfun,一个int类型参数a1,string类型参数b1。
在开线程的时候传参的写法如下:
std::thread(&fun3,m_pfun,a1,b1);

再结合一下上面的说明,第一个参数是函数的地址,第二个参数是谁调用这个函数,对应的这个调用函数的对象地址,第三个以及后面的参数是调用函数的参数。


2. 多线程释放

我们都知道,在使用new的方式创建新的对象,这个对象使用完之后如果不用delete进行释放,那么就会造成内存泄露。

我们创建线程之后,释放通常由 std::thread 的析构函数自动处理,但是关于这一点,存在一个注意点
那如果子线程在运行,但主线程已经跑完了,此时要关闭程序,就会调用析构,可是子线程还在运行,这就会出发异常。
正常的程序应该是,等所有的线程都运行完之后,要确保每个线程在主线程退出之前完成执行,就需要提及到函数join()

join() 用于阻塞当前线程,直到被调用的线程完成执行。调用 join() 后,当前线程会等待直到被 join() 的线程终止,然后继续执行。
确保在线程结束后主线程能够正确处理资源,防止线程终止时资源泄漏。

与之相类似的还有一个函数detach()

detach() 用于将线程与其主线程分离。分离后的线程在后台独立运行,主线程不再需要等待它完成。
子线程在分离后继续运行,即使主线程已经结束。分离线程的资源由系统自动管理。

归纳一下:
join()会阻塞线程,让主线程等join的子线程执行完再接着执行;(插队后排队)
detach()不会阻塞主线程,主线程执行结束也和子线程无关。(从原队中踢出后开新的一队)

所以要确保在线程结束后主线程能够正确处理资源,防止线程终止时资源泄漏,最好的方式其实使用join()函数。


3. 实例

接下来我们看一个实例。
这里我把刚才提到的FUN类放进例子中,通过一个FUN的一个指针m_pfun进行调用fun3函数,最后进行了释放。
这里delete是把指针指向的内存释放,但是指针还是指向那个内存,所以指针还要置空。

fun1和fun2函数和fun3基本类似,少了两个参数,也是延时输出。

我例子中都用了,下面这种方式来确保程序的正常结束。

if (m_thOne.joinable()){m_thOne.join();}

看明白下面的实例,多线程的就可以尝试写一写了。

#include <iostream>
#include <thread>
#include <chrono>class FUN
{
public:void fun3(int a, std::string b){std::cout << "fun3 start" << std::endl;std::chrono::seconds delay(7);std::this_thread::sleep_for(delay);std::cout << "fun3 end" << std::endl;};
};
void fun1()
{std::cout << "fun1 start" << std::endl;std::chrono::seconds delay(3);std::this_thread::sleep_for(delay);std::cout << "fun1 end" << std::endl;
}
void fun2()
{std::cout << "fun2 start" << std::endl;std::chrono::seconds delay(5);std::this_thread::sleep_for(delay);std::cout << "fun2 end" << std::endl;
}
int main()
{std::thread m_thOne = std::thread(&fun1);std::thread m_thTwo = std::thread(&fun2);FUN* m_pfun = new FUN();int a =1;std::string b = "b";std::thread m_thThree = std::thread(&FUN::fun3, m_pfun, a, b);std::cout << "Hello World!\n";if (m_thOne.joinable()){m_thOne.join();}if (m_thTwo.joinable()){m_thTwo.join();}if (m_thThree.joinable()){m_thThree.join();}delete m_pfun;m_pfun = nullptr;return 0;
}

在这里插入图片描述


总结

多线程还是很有用的,C++程序员进阶的必通之路。大学里面学的那些小玩意儿,单线程就能搞定所有,真正的大型项目,还是会有很多多线程相关的。
记住这个多线程demo的简单使用,那么后面进一步拓展就手到擒来了。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • redis的RDB快照详解
  • C学习(数据结构)-->二叉树
  • SpringBoot依赖之Spring Data Redis 实现地理坐标(Geospatial)
  • 响应式Web设计:纯HTML和CSS的实现技巧-1
  • Java 入门指南:注解(Annotation)
  • Linux系统下的容器安全:深入解析与最佳实践
  • 《AI办公类工具PPT系列之三——Gamma APP》
  • appium下载及安装
  • .NET开源纪元:穿越封闭的迷雾,拥抱开放的星辰
  • vue3-基础
  • 从零开始学cv-5: 图像的仿射变换
  • FlinkCEP - Flink的复杂事件处理详解
  • 推荐使用阿贝云免费云服务器、免费虚拟主机
  • docker GBase 8sV8.8使用的常见错误
  • pip出问题了,重装,获取python3.7 get-pip.py
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • CentOS 7 修改主机名
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • Docker: 容器互访的三种方式
  • Less 日常用法
  • Python3爬取英雄联盟英雄皮肤大图
  • swift基础之_对象 实例方法 对象方法。
  • 阿里云Kubernetes容器服务上体验Knative
  • 欢迎参加第二届中国游戏开发者大会
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 一个项目push到多个远程Git仓库
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 一文看透浏览器架构
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • raise 与 raise ... from 的区别
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • ​520就是要宠粉,你的心头书我买单
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (poj1.2.1)1970(筛选法模拟)
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (强烈推荐)移动端音视频从零到上手(上)
  • (四)opengl函数加载和错误处理
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (游戏设计草稿) 《外卖员模拟器》 (3D 科幻 角色扮演 开放世界 AI VR)
  • (转)linux 命令大全
  • (最新)华为 2024 届秋招-硬件技术工程师-单板硬件开发—机试题—(共12套)(每套四十题)
  • ./configure、make、make install 命令
  • .net反编译的九款神器
  • .NET开源、简单、实用的数据库文档生成工具
  • .NET未来路在何方?
  • []AT 指令 收发短信和GPRS上网 SIM508/548
  • [20190113]四校联考
  • [AIGC] Java 和 Kotlin 的区别