索引
- 1 std::async
- 2 std::packaged_task
- 3 std::promise
- 4 std::shared_future
- 参考
1 std::async
先用std::async启动一个异步任务,它返回一个持有计算结果的std::future,通过std::future::get即可阻塞线程,直到期值的状态为ready并返回该结果
int f()
{
return 1;
}
int main()
{
std::future<int> ft = std::async(f);
std::cout << ft.get(); // 1
}
int f();
// 函数必须异步执行,即运行在不同的线程上
auto ft1 = std::async(std::launch::async, f);
// 函数只在返回的期值调用get或wait时运行
auto ft2 = std::async(std::launch::deferred, f);
// 不指定时的默认启动策略是对两者进行或运算的结果
// auto ft3 = std::async(f)等价于
auto ft3 = std::async(std::launch::async | std::launch::deferred, f);
2 std::packaged_task
packaged_task类模板也是定义于future头文件中,它包装任何可调用 (Callable) 目标,包括函数、 lambda 表达式、 bind 表达式或其他函数对象,使得能异步调用它,其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。简言之,将一个普通的可调用函数对象转换为异步执行的任务。通过packaged_task包装后,可以通过thread启动或者仿函数形式启动,其执行结果返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。
#include <iostream> // std::cout
#include <thread> // std::thread
#include <chrono>
#include <future>
using namespace std;
//普通函数
int Add(int x, int y)
{
return x + y;
}
void task_lambda()
{
//包装可调用目标时lambda
packaged_task<int(int,int)> task([](int a, int b){ return a + b;});
//仿函数形式,启动任务
task(2, 10);
//获取共享状态中的值,直到ready才能返回结果或者异常
future<int> result = task.get_future();
cout << "task_lambda :" << result.get() << "\n";
}
void task_thread()
{
//包装普通函数
std::packaged_task<int (int,int)> task(Add);
future<int> result = task.get_future();
//启动任务,非异步
task(4,8);
cout << "task_thread :" << result.get() << "\n";
//重置共享状态
task.reset();
result = task.get_future();
//通过线程启动任务,异步启动
thread td(move(task), 2, 10);
td.join();
//获取执行结果
cout << "task_thread :" << result.get() << "\n";
}
int main(int argc, char *argv[])
{
task_lambda();
task_thread();
return 0;
}
3 std::promise
一个std::promise只能关联一个std::future,关联多次时将抛出std::future_error异常
std::promise<int> ps;
std::future<int> ft = ps.get_future();
ps.set_value(42); // set_value还会将状态设置为就绪
std::cout << ft.get(); // 42
void f(std::promise<void> ps)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
ps.set_value();
}
int main()
{
std::promise<void> ps;
std::future<void> ft = ps.get_future();
std::thread t(f, std::move(ps));
ft.wait(); // 阻塞直到set_value,相当于没有返回值的get
t.join();
}
4 std::shared_future
std::future调用get后就无法再次get,也就是说只能获取一次数据,此外还会导致所在线程与其他线程数据不同步。std::shared_future就可以解决此问题
//第一种
std::promise<int> ps;
std::future<int> ft(ps.get_future());
std::shared_future<int> sf(std::move(ft));
//第二种
// std::future隐式转换为std::shared_future
std::promise<int> ps;
std::shared_future<int> sf(ps.get_future());
//第三种
std::promise<int> ps;
auto sf = ps.get_future().share();
参考
1.https://downdemo.gitbook.io/cpp-concurrency-in-action-2ed
2.https://blog.csdn.net/c_base_jin/article/details/79541301