# c++中的std::future与std::shared_future
# std::future
在C++中,std::future
是一个类模板,用于接收尚未计算的异步执行任务的结果,也就是未来值,用来获取异步操作的未来值。
获取std::future
对象的三种方式:
std::async
std::packaged_task
的get_future
函数std::promise
的get_future
函数
异步操作准备将一个修改发布给future
对象时,可以通过修改和future
对象关联的共享状态来实现,如std::promise::set_value
方法。
std::future
模板类支持的成员函数有:
future& operator=( future&& other ) noexcept;
将一个future
对象移动给当前变量std::shared_future<T> share() noexcept;
传输*this
的共享状态,多个std::shared_future
对象可以在多个线程共享同个共享状态。T get()
获取future
对象的关联结果wait
等待直到结果获取到值wait_for/wait_until
等待,并设置超时
# std::shared_future
功能总体和std::future
相同,都是为了从异步操作中获取函数执行的结果。
不过,使用std::shared_future
可以使得多个线程支持共同等待同一共享变量的值。
与std::future
相比,std::shared_future
类的对象支持复制,支持多个std::shared_future
对象关联同个共享状态值。
如果每个线程复制获取了std::shared_future
对象,那么同时在多个线程中获取同个共享状态也是线程安全的。
std::shared_future
的机制有些类似条件变量,同时给所有等待的线程发信号。
# 实例
- std::future
#include <future>
#include <thread>
#include <iostream>
void setPromiseValue1(std::future<int> &fut)
{
std::cout << "waitting1 to get value" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
int value = fut.get();
std::cout << "promise1 value: " << value << std::endl;
}
int main(int argc, char* argv[])
{
std::promise<int> prom;
std::future<int> fut = prom.get_future();
std::thread t1(setPromiseValue1, std::ref(fut));
std::cout << "before set value...\n";
prom.set_value(100);
t1.join();
}
// before set value...
// waitting1 to get value
// promise1 value: 100
上面的例子,如果再创建一个线程,依然使用fut
对象,并在线程任务中调用fut.get
,那么程序将报错,因为std::future
对象不支持多个线程共享,get
也仅支持调用一次。
- std::shared_future
#include <chrono>
#include <future>
#include <iostream>
int main()
{
std::promise<void> ready_promise, t1_ready_promise, t2_ready_promise;
std::shared_future<void> ready_future(ready_promise.get_future());
std::chrono::time_point<std::chrono::high_resolution_clock> start;
auto fun1 = [&, ready_future]() -> std::chrono::duration<double, std::milli>
{
t1_ready_promise.set_value();
ready_future.wait(); // waits for the signal from main()
return std::chrono::high_resolution_clock::now() - start;
};
auto fun2 = [&, ready_future]() -> std::chrono::duration<double, std::milli>
{
t2_ready_promise.set_value();
ready_future.wait(); // waits for the signal from main()
return std::chrono::high_resolution_clock::now() - start;
};
auto fut1 = t1_ready_promise.get_future();
auto fut2 = t2_ready_promise.get_future();
auto result1 = std::async(std::launch::async, fun1);
auto result2 = std::async(std::launch::async, fun2);
// wait for the threads to become ready
fut1.wait();
fut2.wait();
// the threads are ready, start the clock
start = std::chrono::high_resolution_clock::now();
// signal the threads to go
ready_promise.set_value();
std::cout << "Thread 1 received the signal "
<< result1.get().count() << " ms after start\n"
<< "Thread 2 received the signal "
<< result2.get().count() << " ms after start\n";
}
上面的代码中ready_promise
返回的是ready_future
,两个线程中都有调用其wait
阻塞,直到与之关联的ready_promise
设置值后才会继续运行。
# reference
1.https://en.cppreference.com/w/cpp/thread/future (opens new window)
2.https://en.cppreference.com/w/cpp/thread/shared_future (opens new window)