前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++11】 让多线程开发变得简单--异步操作

【C++11】 让多线程开发变得简单--异步操作

作者头像
CPP开发前沿
发布2021-11-16 14:15:53
6440
发布2021-11-16 14:15:53
举报
文章被收录于专栏:CPP开发前沿CPP开发前沿

C++ 11中提供了异步操作相关类和函数,不同的类具备不同的功能,总体来说类主要有:std::future,std::promise,std::package_task,函数主要是std::async。

1 异步操作类

上面三个类的主要功能是:

  • std::future:该类主要作为异步结果传输通道,方便获取线程函数的返回值;
  • std::promise:用来包装一个值,和futre绑定使用,方便线程赋值;
  • std::package_task:包装一个可调用对象,和future配合使用,方便异步调用。

1.1 std::future

在thread库中提供了该future访问异步操作的结果,由于异步结果不能马上取得,只能在未来某个时候进行获取,这个结果是一个未来值,因此叫做future。通过查询future状态获取结果,future由三种状态组成,分别是:

  • Deferred:异步操作还没开始
  • Ready:异步操作已经完成
  • Timeout:异步操作超时

在实际编码中,可以通过判断这三种内部状态异步获取执行结果。代码示例如下:

代码语言:javascript
复制
std::cout << "checking, please wait";
  std::chrono::milliseconds span (1000);
  do{
      status = fut.wait_for(span);
      if(status == std::future_status::deferred)
      {
          std::cout << "\ndeferred" << std::flush;
      }
      else if(status == std::future_status::timeout)
      {
          std::cout << "\ntimeout" << std::flush;
      }
      else if(status == std::future_status::ready)
      {
          std::cout << "\ready" << std::flush;
      }
  }while(status != std::future_status::ready);

1.2 std::promise

使用std::promise可以实现在两个不同线程之间的数值传递。使用方法如下:

代码语言:javascript
复制
void print_set(std::promise<int> &pro)
{
    std::cout << "set value: " << "100" << '\n';
    pro.set_value(100);
}

void print_int (std::future<int>& fut) {
  int x = fut.get();
  std::cout << "value: " << x << '\n';
}

int main ()
{
  std::promise<int> prom;                  
  std::future<int> fut = prom.get_future();     
  std::thread th2 (print_set, std::ref(prom));  
  std::thread  th1 (print_int, std::ref(fut));                                                
  th1.join();
  th2.join();
  return 0;
}

上面的代码运行结果如下:

代码语言:javascript
复制
set value: 100
value: 100

1.3 std::package_task

和std::promise类似,需要结合future使用,但不同的是std::package_task包装的是一个函数,以此方便异步调用。使用方法如下:

代码语言:javascript
复制
int Add(int x,int y)
{
    return (x+y);
}

int main ()
{
  std::packaged_task<int(int,int)> pFun(Add);              
  std::future<int> fut = pFun.get_future();     
  std::thread th2 (std::move(pFun), 3,2);  
  int iRes = fut.get();
  std::cout<<"iRes="<<iRes<<std::endl;
  th2.join();
  return 0;
}

程序运行结果为:iRes=5

2 异步操作函数:async

相对前面的异步操作类,std::async要高级的多,且可以直接创建异步的task类,异步返回结果保存在future中,在获取线程函数返回结果时,使用get()获取返回值,如果不需要值则使用wait()方法。

std::async原型如下:

代码语言:javascript
复制
future<typename result_of<Fn(Args...)>::type>
    async (launch::async|launch::deferred, Fn&& fn, Args&&... args);

原型参数说明如下:

  • launch::async: 调用async后就开始启动线程
  • launch::deferred:延迟启动线程,等到后面调用了wait、get时在启动线程。
  • fn:线程函数
  • args:线程函数参数

async基本用法如下:

代码语言:javascript
复制
bool is_prime (int x) {
  std::this_thread::sleep_for(std::chrono::seconds(3));
  for (int i=2; i<x; ++i) if (x%i==0) return false;
  return true;
}

int main ()
{
  // call function asynchronously:
  std::future<bool> fut = std::async (is_prime,444444443); 
  std::future_status status;
  // do something while waiting for function to set future:
  std::cout << "checking, please wait";
  std::chrono::milliseconds span (1000);
  do{
      status = fut.wait_for(span);
      if(status == std::future_status::deferred)
      {
          std::cout << "\ndeferred" << std::flush;
      }
      else if(status == std::future_status::timeout)
      {
          std::cout << "\ntimeout" << std::flush;
      }
      else if(status == std::future_status::ready)
      {
          std::cout << "\ready" << std::flush;
      }
  }while(status != std::future_status::ready);
  
  bool x = fut.get();     // retrieve return value

  std::cout << "\n444444443 " << (x?"is":"is not") << " prime.\n";

  return 0;
}

上面代码的运行如果为:

代码语言:javascript
复制
checking, please wait
"\n444444443 is prime."

async是更高层次的异步操作,在实际编码时无需关注线程创建细节,就可以方便的获取线程执行状态和结果;一般情况下,默认使用launch::async参数。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CPP开发前沿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档