天天看点

C++多线程之旅-future等待事件

目录

      • 前言
      • future
      • 总结

前言

前一篇文章讲到了关于

condition_variable

的使用,但是这种方法太过于底层了,不是很方面,而且需要对调用方进行操作。这样对于程序员来说太过于麻烦,引入一个全新的接口,让被调用的线程自动进行,调用线程直接调用结果就行。这就是C++引入的

future()类

,而且这种方式可以在不同线程之间传递数据。

我们首先假设情况现在有两个线程,线程A等待线程B执行结果,线程B执行完成之后将结果返回给线程A。之前在

condition_variable

里面是在线程外定义一个全局变量,但是这样会导致数据不安全有泄露的风险。

future

首先看一个例子:

string fun_1()  {
    return "123";
}

int main() {
    auto x = async(fun_1);
    cout << "456";
    cout << x.get();
}
           

此时x获取到的是

future<string>

类型,然后在调用.get()函数获得其中包含的值。而且线程

fun_1

只有在

.get()

时才调用。执行结果如下:

C++多线程之旅-future等待事件

这里面有两个函数,一个是

async

,另一个是

future

async

使用方法和

thread类

类似,但是多了一个函数参数。

async(A, B, C,....)

  • 其中这个A:是表示你是否创建一个新线程,参数类型是std::launch类型。
    • std::launch::deferred:表示该函数会延迟启动,直到

      future

      上调用

      wait()

      get()

    • std::launch::async:表示该函数必须运行在他自己的线程上;
    • std::launch::deferred | std::launch::async:表明该函数可以有具体实现来选择(默认最后一个);
  • B和C:分别是需要传入的函数和函数的参数,和thread一样,函数的参数是通过副本传入,如果需要传入引用则需要使用std::ref类。

future可以从异步任务中获取结果,一般与std::async配合使用,std::async用于创建异步任务,实际上就是创建一个线程执行相应任务。

  • std::future::get获取结果,如果调用过程中,任务尚未完成,则主线程阻塞至任务完成。
  • std::future::wait_for等待结果返回,wait_for可设置超时时间,如果在超时时间之内任务完成,则返回std::future_status::ready状态;如果在超时时间之内任务尚未完成,则返回std::future_status::timeout状态。

前面那个例子我们看了get()方法,我们来测试一下这个wait_for()方法:

string fun_2() {
    this_thread::sleep_for(chrono::seconds(3));
    return "hello";
}
int main() {
    auto x = async(fun_2);
    cout << "456  ";
    if  (x.wait_for(chrono::seconds(1)) == future_status::timeout)
        cout << "time out" << endl;
    else
        cout << x.get();
}
           

线程fun_2执行时,线程睡眠3秒,主线程仅仅只等待1秒,就会出现返回time_out标志。

C++多线程之旅-future等待事件

修改相应的等待时间参数之后得到的结果就是另外一个样子了。

C++多线程之旅-future等待事件

总结

在使用异步线程时,采用future比condition_variable简单而且无需考虑内部实现的过程。所以在使用是尽量使用这个,而且还可以实现在不同线程之间传递数据,避免使用全局变量提高系统安全性。