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
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++多线程回调可以通过线程池技术实现。具体实现思路如下: 1. 创建一个线程池,线程池中包含多个线程,这些线程都是可重用的资源。 2. 在主线程中创建一个任务队列,将需要异步处理的任务加入到任务队列中。 3. 线程池中的线程会不断地从任务队列中取出任务进行处理。 4. 当任务处理完成后,线程会将处理结果通过回调函数返回给主线程。 下面是一个简单的C++多线程回调的例子: ```cpp #include <iostream> #include <thread> #include <mutex> #include <condition_variable> #include <queue> #include <functional> using namespace std; class ThreadPool { public: ThreadPool(int numThreads) : stop(false) { for (int i = 0; i < numThreads; ++i) { threads.emplace_back( [this] { for (;;) { function<void()> task; { unique_lock<mutex> lock(this->queue_mutex); this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); if (this->stop && this->tasks.empty()) return; task = move(this->tasks.front()); this->tasks.pop(); } task(); } } ); } } template<class F> void enqueue(F&& f) { { unique_lock<mutex> lock(queue_mutex); tasks.emplace(forward<F>(f)); } condition.notify_one(); } ~ThreadPool() { { unique_lock<mutex> lock(queue_mutex); stop = true; } condition.notify_all(); for (thread& worker : threads) worker.join(); } private: vector<thread> threads; queue<function<void()>> tasks; mutex queue_mutex; condition_variable condition; bool stop; }; void asyncTask(int x, int y, function<void(int)> callback) { int result = x + y; callback(result); } int main() { ThreadPool pool(4); pool.enqueue([] { cout << "Task 1" << endl; }); pool.enqueue([] { cout << "Task 2" << endl; }); pool.enqueue([] { cout << "Task 3" << endl; }); pool.enqueue([] { cout << "Task 4" << endl; }); pool.enqueue([] { cout << "Task 5" << endl; }); pool.enqueue([] { asyncTask(1, 2, [](int result) { cout << "Result: " << result << endl; }); }); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值