C++11 Tasks 线程与任务的区别

tasks是最新额外添加的C++标准。
这是给了一个比线程更好的抽象。
通常情况下,这应该是你的第一选择。


Tasks行为就像是数据通道。
一方面,发送者设置一个值。
另一方面,接收者获取这个值。
发送这人通常被称为promise, 接收者被称为future.
或者换句话说就是, 发送者承诺提供一个值, 接收者在将来可以获取到它。
这里写图片描述

来看一些更多的细节。

  • 发送者可以提供给多个future。
  • 除了值,发送者还可以提供通知或者异常。
  • future阻塞调用get。
    这意味着,如果future要调用get,它必须等到promise把值放进数据通道中。

tasks 三种变体

1、被异步函数std::async所调用。
2、使用std::packaged_task为一个callable作为一个简单的包装
3、一个明确的pair,std::promisestd::future

想要知道线程和tasks的区别,最好的方法就是比较它们。

线程和tasks对比
让我们用简单的代码阐明它们的不同之处:

int res;
std::thread t([&]
{
    res = 3 + 4;
});
t.join();
std::cout << res << std::endl;

auto fut = std::async([]
{
    return 3 + 4;
});

std::cout << fut.get() << std::endl;

无论子线程还是promise都计算了3+4的和,并且返回了执行结果.
std::async的调用在fut和std::async两端生成了一个数据通道。
fut是个future,std::async是个promise。
future通过调用fut.get()获取值。当然值是由promise提供的。
future值的获取可以在稍后的时间点执行。


那区别是啥啊?
这里写图片描述

  • 线程需要<thread>头文件,而task需要<future>头文件。
  • 线程的参与者是创建主线程和子线程,task的参与者是promise和future。
  • 线程操作的共享变量res是通过子线程传递给父线程方式计算的结果。
  • 然而promise 和 future使用一个公共的数据通道,std::async创建的这个数据通道,使用future变量fut.get获取计算的结果。
  • 使用线程你必须使用锁来保护共享变量。
  • 但是promise 和 future不会有机会出现竞争条件。
  • 主线程等待子线程结束需要子线程调用join函数;然而fut.get 调用直接阻塞。
  • 如果子线程中存在异常,则子线程和创建者线程终止,最终整个程序gg。
  • 然而promise可以为future返回一个异常,future必须处理这个异常。
  • 子线程只能通过值向主线程传递数据,但是promise能传递值,异常,消息通知等给future。

线程和task关键的区别在于tasks的抽象级别更高。
tasks不会自动生成线程,确切地说,C++在运行时决定是否应该创建一个线程。
决定的依据是:有效载荷有多重?有多少核心可用?系统负载有多高?


原文地址:

http://www.modernescpp.com/index.php/tasks

猜你喜欢

转载自blog.csdn.net/y396397735/article/details/82317693