参考:https://blog.csdn.net/lizhichao410/article/details/123732787
使用背景
在C++中使用std::thread可创建一个线程,使用互斥量std::mutex来确保多个线程对共享数据的读写操作同步问题;使用std::condition_variable来解决线程执行顺序的同步问题。那么多个线程之间怎么传递数据呢?其中一种做法是使用一个全局变量,然后让线程之间互斥的访问就可以传递数据,还有一种做法就是使用std::future和std::async。
同步操作和异步操作
同步操作:在函数调用时,在没有得到结果之前该调用不返回,由调用者主动等待这个调用的结果。
异步操作:在函数调用之后,这个调用就直接返回了,没有返回结果。即当一个异步过程调用发出后,调用者不会立刻得到结果。
std::future
std::future是一个类模板,用来保存一个异步操作的结果,即这是一个未来值,只能在未来某个时候进行获取。
- get():等待异步执行结果并返回结果,若得不到结果就会一直等待。
- wait():用于等待异步操作执行结束,但并不返回结果
- wait_for():阻塞当前进程,等待异步任务运行一段时间后返回其状态std::future_status,状态是枚举类型:
- std::future_status::deferred:异步操作还没有开始
- std::future_status::ready:异步操作已经完成
- std::future_status::timeout:异步操作超时
std::async
std::async是一个函数模板,用来启动一个异步任务,和std::thread类似,但std::async是更高级的抽象,异步返回结果保存在std::future中,使用者可以不必进行线程细节的管理。std::async有两种启动策略:
- std::launch::async : 函数必须以异步方式运行,即创建新的线程。
- std::launch::deferred:
函数只有在std::async所返回的std::future进行get()或wait()调用时才执行,并且调用方会阻塞至运行结束,否则不执行。
若没有指定策略,则会执行默认策略,将会由操作系统决定是否启动新的线程。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include <iostream> #include <thread> #include <future>
int getDataDemo() { std::cout << "start data query, " << "threadID: " << std::this_thread::get_id() << std::endl; std::this_thread::sleep_for(std::chrono::seconds(5)); return 100; }
int main() { std::cout << "execute data query, " << "threadID: " << std::this_thread::get_id() << std::endl; std::future<int> m_future = std::async(std::launch::async, getDataDemo); std::future_status m_status; do { m_status = m_future.wait_for(std::chrono::seconds(1)); switch (m_status) { case std::future_status::ready: std::cout << "data query complete, " << "threadID: " << std::this_thread::get_id() << std::endl; break; case std::future_status::timeout: std::cout << "data query is running, " << "threadID: " << std::this_thread::get_id() << std::endl; break; case std::future_status::deferred: std::cout << "data query delay, " << "threadID: " << std::this_thread::get_id() << std::endl; m_future.wait(); break; default: break; } } while (m_status != std::future_status::ready); int ret = m_future.get(); std::cout << "data query result, " << ret << "threadID: " << std::this_thread::get_id() << std::endl; }
|