《C++标准库》学习笔记 — STL — 并发 — 启动线程

《C++标准库》学习笔记 — STL — 并发一、高级接口 async() 和 Future1、实例一、高级接口 async() 和 Futureasync() 提供一个接口,让一个 (caller object) 成为一个独立线程。class future 允许你等待线程结束并获取其结果。1、实例考虑下面的操作:func1() + func2()在单线程中,整体处理时间是 func1() 所花时间加上 func2() 所花时间,再加上计算总和所花时间。如果我们尝试在多线程中实现这样的操作
摘要由CSDN通过智能技术生成

一、高级接口 async() 和 Future

async() 提供一个接口,让一个 (caller object) 成为一个独立线程。
class future 允许你等待线程结束并获取其结果。

1、实例

考虑下面的操作:

func1() + func2()

在单线程中,整体处理时间是 func1() 所花时间加上 func2() 所花时间,再加上计算总和所花时间。

如果我们尝试在多线程中实现这样的操作,可以将总时间限制为 func1() 所花时间和 func2() 所花时间中的较大者加上计算总和的时间:

#include <iostream>
#include <random>
#include <future>
#include <thread>
#include <chrono>
using namespace std;

int doSomething(char c)
{
   
	default_random_engine e(time(0));
	uniform_int_distribution u(10, 1000);

	for (int i = 0; i < 10; ++i)
	{
   
		this_thread::sleep_for(chrono::milliseconds(u(e)));
		cout.put(c).flush();
	}

	return u(e);
}

int func1()
{
   
	return doSomething('.');
}

int func2()
{
   
	return doSomething('+');
}

int main()
{
   
	future<int> result1(async(func1));

	int result2 = func2();

	int result = result2 + result1.get();

	cout << endl << "result is " << result << endl;
}

在这里插入图片描述
我们首先使用 async() 尝试在后台运行 func1(),并将结果赋值给某个 std::future object。这种调用是异步的,相当于在一个独立的线程中执行该方法,因此不会阻塞主线程。基于两个原因,返回 future object 是必要的:

  • 它允许我们获取在独立线程中执行方法的返回值(或异常)
  • 它可以确保传递给目标函数对象会被执行。因为 async() 函数的调用不代表目标函数一定会开始执行。

我们调用 get() 函数会发生以下三件事之一:

  1. 如果 func1() 已在独立线程中启动且结束,我们可以立即获得其返回值
  2. 如果 func1() 被启动但尚未结束,会导致主线程停滞直到该函数运行结束,然后我们才能获取到运行结果
  3. 如果 func1() 尚未启动,会被强迫启动如同一个同步调用。

调用 async() 并不保证传入的函数一定会被启动和结束。如果有个线程处于可用状态,那么它的确会被启动,但如果不是这样(在单线程环境中,或线程资源已被占满),这一调用会被推迟至你明确说你需要其结果(调用 get() 时)或只是希望目标函数完成其任务(调用 wait())。

所以,我们可以定义让程序更快速的一般做法:修改程序使它受益于并行处理(如果平台支持),但仍能够在单线程环境中运作。为了到达这个目标,我们需要:

  1. #include <future>
  2. 传递某些可并行执行的函数,交给 std::async() 作为一个可调用对象
  3. 将执行结果赋值给一个 future object
  4. 当需要那个被启动函数的执行结果,或确保该函数结束,就调用 future::get() 方法。
    需要注意的是,上述原则只是用于不发生数据竞争的情况下。

另外,为优化程序性能,我们必须确保在最必要时才索取目标函数的执行结果。否则,如下的代码可能会产生意外的运行情况:

int result = func2()+ result1.get();

在C++中,上述代码中两个函数(func2()get())的调用顺序是不确定的。因此,这样的调用可能完全无法实现异步执行的效果。

为了获得最佳的执行效果,我们应该将 async() 和调用 get() 之间的距离最大化。

2、发射策略

async() 函数提供了一个参数用于设置发射策略:

future<int> result1(async(launch
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值