博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++:多线程
阅读量:4298 次
发布时间:2019-05-27

本文共 3380 字,大约阅读时间需要 11 分钟。

C++:多线程

  • 验证对比其他多线程实现方法的效率问题

1. 什么是多线程以及为什么使用多线程

不再啰嗦

2. 多线程实现方法

2.1 通过thread类来实现

从C++ 11开始,提供了thread来实现多线程,使用简单方便。没有和其他实现thread的方法进行对比。后续可以考虑测试一下

#include 
std::thread t1(func, para1, para2, ... );t1.join();

2.1.1 类外函数使用类内函数创建线程

类外多线程调用类成员函数

当我们使用类成员函数创建子线程时,会报错,无法创建子进程。

  • 原因:类中的成员函数,编译器会为它添加 this 指针,
  • 解决方案: 推荐使用方案3
    1. 使用 静态你成员函数代替原来的成员函数。当然这样的话会对之前定义的成员函数造成一定的影响。静态成员函数只能访问静态成员变量,解决此问题的一种途径是可以在调用类静态成员函数(线程函数)时将this指针作为参数传入,并在改线程函数中用强制类型转换将this转换成指向该类的指针,通过该指针访问非静态成员。

    2. 不定义类成员函数为线程函数,而将线程函数定义为类的友元函数。这样,线程函数也可以有类成员函数同等的权限;

    3. 🤩 将线程创建代码修改为如下格式

      std::thread t(std::mem_fn(&Myclass::func), Object, arg1, ...)// Object即我们创建的对象实例

      参考链接:

2.1.2 类内成员函数使用类内成员函数创建线程

类成员函数中实现多线程调用同一个类中的成员函数

类成员函数中实现多线程,调用的函数是同一个类中的成员函数,实现代码如下:

#include 
#include
class foo{
public: void make_foo_func_thread() {
t=std::thread(&foo::foo_func, this); t.join(); }private: std::thread t; void foo_func() {
std::cout << "Hello\n"; }};int main(){
foo f; f.make_foo_func_thread();}

2.1.3 同步线程与异步线程

线程的join和detach,请参考:

  • join() 是阻塞当前执行的线程,等待线程执行完毕再继续下一步操作

    注意,如果在线程后面立即添加 join(), 那么多线程会串行执行,如下:

    thread t1(func1, a, b, sum1);	t1.join();	thread t2(func1, x, y, sum2);	t2.join();
  • detach 是将线程从当前线程分离出去,即不受阻塞,操作系统会将其独立对待

通常称分离线程为守护线程

2.1.4 多线程与vector

我们在创建多线程时,经常会结合vector创建多线程,伪代码如下:

#include 
#include
int main(){
std::vector
threads; std::thread t1(func1); /// ... 创建线程,并将线程添加到vector 中 /// threads.push_back(t1); // 错误,本小节下有说明 threads.push_back(std::move(t1)); //正确 threads.push_back(std::thread(&threadTest::func1, this)); // 也可以(这里实现的是类成员函数创建的线程) threads.emplace_back(t1); //错误 for(auto& func:threads) {
func.join(); }}

实现过程中我们可能会遇到这样的错误提示:

error: use of deleted function ‘std::thread::thread(const std::thread&)

参考 stackflow上的问答,了解到:

std::thread 是不可复制的,为了保证线程的唯一性,push_back操作会先创建元素,然后再进行一次拷贝,所以这里会报错。

3. 获取线程的返回值

3.1 传统方法:线程间共享指针

#include 
#include
#include
#include
using namespace std;void func1(int x, int y, int *ans){
*ans = x + y;}int main(){
int a, b, x, y; a = 1; b = 2; x = 3; y = 4; int *sum1 = new int(0); int *sum2 = new int(0); thread t1(func1, a, b, sum1); t1.join(); thread t2(func1, x, y, sum2); t2.join(); cout << "sum1:" << *sum1 << endl; cout << "sum2:" << *sum2 << endl; delete sum1; delete sum2; system("pause"); return 0;}// ==============================// sum1:3// sum2:7

3.2 使用std::future和std::promise

std::future 和std::promise是封装好的两个类模板,这两个类配合使用,头文件是

void func3(int x, int y, std::promise
&promiseObj) {
promiseObj.set_value(x + y);}int main(){
//计算(a+b)/(x+y) //用三个线程,一个线程计算a+b,另一个线程计算x+y int a, b, x, y; a = 10, b = 8, x = 2, y = 4; int sum1, sum2; //声明一个类 std::promise
promiseObj; //将future和promise关联 std::future
futureObj = promiseObj.get_future(); //模板传参的时候使用ref,否则传参失败 std::thread t1(func3, a, b, ref(promiseObj)); t1.join(); //获取值 sum1 = futureObj.get(); std::cout << "sum1=" << sum1 << std::endl; //不能直接复用上面的future和promise std::promise
promiseObj2; std::future
futureObj2 = promiseObj2.get_future(); std::thread t2(func3, x, y, ref(promiseObj2)); t2.join(); sum2 = futureObj2.get(); std::cout << "sum2=" << sum2 << std::endl; std::cout << "sum1/sum2=" << sum1 / sum2 << std::endl; std::system("pause"); return 0;}

转载地址:http://gtnws.baihongyu.com/

你可能感兴趣的文章
浅析 Laravel 官方文档推荐的 Nginx 配置
查看>>
Swagger在Laravel项目中的使用
查看>>
Laravel 的生命周期
查看>>
CentOS Docker 安装
查看>>
Nginx
查看>>
Navicat远程连接云主机数据库
查看>>
Nginx配置文件nginx.conf中文详解(总结)
查看>>
Mysql出现Table 'performance_schema.session_status' doesn't exist
查看>>
MySQL innert join、left join、right join等理解
查看>>
vivado模块封装ip/edf
查看>>
sdc时序约束
查看>>
Xilinx Jtag Access/svf文件/BSCANE2
查看>>
NoC片上网络
查看>>
开源SoC整理
查看>>
【2020-3-21】Mac安装Homebrew慢,解决办法
查看>>
influxdb 命令行输出时间为 yyyy-MM-dd HH:mm:ss(年月日时分秒)的方法
查看>>
已知子网掩码,确定ip地址范围
查看>>
判断时间或者数字是否连续
查看>>
docker-daemon.json各配置详解
查看>>
Mac 下docker路径 /var/lib/docker不存在问题
查看>>