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

CPP多线程1:C++11的std::thread

在C中已经有一个叫做pthread的东西来进行多线程编程,但是并不好用 ,所以c++11标准库中出现了一个叫作std::thread的东西。

std::thread常用成员函数

构造&析构函数
在这里插入图片描述
常用成员函数
在这里插入图片描述
例一:thread的基本使用

#include <iostream>
#include <thread>
using namespace std;void doit() { for(int i=0;i<10;i++){cout << "World!" << endl;} 
}int main() {thread a([]() {for(int i=0;i<10;i++){cout << "Hello " << flush;} });thread b(doit);a.join();b.join();return 0;
}

输出结果:

Hello, World!

或者是

World!
Hello,

那么,为什么会有不同的结果呢?

这就是多线程的特色!

多线程运行时是以异步方式执行的,与我们平时写的同步方式不同。异步方式可以同时执行多条语句。

在上面的例子中,我们定义了2个thread,这2个thread在执行时并不会按照一定的顺序。打个比方,2个thread执行时,就好比赛跑,谁先跑到终点,谁就先执行完毕。

例二:thread执行有参数的函数

#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
void countNumber(int id, unsigned int n) {this_thread::sleep_for(chrono::seconds(10));cout << "Thread " << id <<"'s val is "<<n<<". And it's finished!" << endl;
}
int main() {thread th[10];for (int i = 0; i < 10; i++)th[i] = thread(countNumber, i, 10000);for (int i = 0; i < 10; i++)th[i].join();return 0;
}

这个例子中我们在创建线程时向函数传递了一些参数,但如果要传递引用参数呢?是不是像这个例子中直接传递就行了?其实不行,因为thread在传递参数时,是以右值传递的。

那么我们该如何传递一个左值呢?std::ref和std::cref很好地解决了这个问题。

std::ref 可以包装按引用传递的值。

std::cref 可以包装按const引用传递的值。

例三:thread执行带有引用参数的函数

#include <iostream>
#include <thread>
using namespace std;template <typename T>
void changeValue(T& x,T val){x=val;
}int main(){cout<<"---------before------------"<<endl;thread th[100];int nums[100]{0};for(auto& x:nums)cout<<x<<" ";for (int i = 0; i < 100; i++)th[i] = thread(changeValue<int>, ref(nums[i]), i+1);cout<<endl<<"---------after------------"<<endl;for (auto& t : th) t.join();for(auto& x:nums)cout<<x<<" ";cout<<endl;return 0;
}

例四:thread启动类的成员函数

基本语法

std::thread t(&ClassName::MemberFunction, objectPointer, args...);

其中:

  • &ClassName::MemberFunction 是成员函数的指针。

  • objectPointer 是指向类实例的指针或引用,指明成员函数在哪个对象上执行。

  • args… 是传递给成员函数的参数。

#include <iostream>
#include <thread>
using namespace std;class Count{
public:Count():m_count(0){}void increment(int numInterations){for(int i=0;i<numInterations;i++)m_count++;}int getCount(){return m_count;}  
private:int m_count;
};int main(){const int numIterations=100;Count count;thread th(&Count::increment,&count,numIterations);th.join();cout<<count.getCount()<<endl;return 0;
}

注意事项

  • 线程是在thread对象被定义的时候开始执行的,而不是在调用join函数时才执行的,调用join函数只是阻塞等待线程结束并回收资源。

  • 分离的线程(执行过detach的线程)会在调用它的线程结束或自己结束时释放资源。

  • 线程会在函数运行完毕后自动释放,不推荐利用其他方法强制结束线程,可能会因资源未释放而导致内存泄漏。

  • 没有执行join或detach的线程在程序结束时会引发异常。

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

相关文章:

  • 再发一篇博客
  • 10.从开始写LINUX内核——时钟中断
  • 从零开始构建在线语言翻译网站:完整开发指南
  • 批次防混的“电子锁”:浪智WMS系统 如何用绑定技术终结出入库乱局
  • 深入理解 Python 元类中的 __prepare__ 方法:掌控类属性定义顺序的艺术
  • 【Html网页模板】赛博朋克数据分析大屏网页
  • 聊聊智慧这个东西之三:从食物的毒性、偏性聊起
  • 一种采用双PID串级控制的双轮自平衡车的研制-论文复现与分析
  • 使用影刀RPA实现快递信息抓取
  • XSS攻击:从原理入门到实战精通详解
  • Python代码规范与静态检查(ruff/black/mypy + pyproject.toml + Makefile)自动化工具链介绍
  • 8.从零开始写LINUX内核——初始化中断控制芯片
  • 实时计算 记录
  • 小杨的H字矩阵-洛谷B3924 [GESP202312 二级]
  • Python环境下载安装、以及环境配置教程(Windows版)
  • Vue组件基础解析
  • B+树索引分析:单表最大存储记录数
  • AI搜索:大模型商业落地的“第一束光”,照见了什么?
  • 车灯的技术和未来方向
  • Python列表与元组:数据存储的艺术
  • 【科研绘图系列】R语言在DOM再矿化数据分析与可视化中的应用
  • 力扣(接雨水)——基于最高柱分割的双指针
  • LLaVA
  • 胶质母细胞瘤对化疗的敏感性由磷脂酰肌醇3-激酶β选择性调控
  • MySQL 的 DDL / DML / DQL / DCL 做一次系统梳理:概念区别→常用语法→特点与注意点→实战小例子→常见面试/坑点速记
  • 解构下一-代 AI 智能体:超越 LLM,深度解析三大核心支柱——上下文、认知与行动
  • 基础数据结构
  • Linux——进程管理和计划任务管理
  • Python中*args和**kwargs
  • 基于springboot的在线视频教育管理系统设计与实现(源码+文档+部署讲解)