c++11异步编程

     在c++11之前我们想要获取一个线程的执行结果,通常的的手段就是给线程传一个指针或者引用,然后把执行结果给这个指针或者引用,这样我们就可以在其他的线程例获取执行结果了,但是这种方法有一个缺点就是,我们并不知道什么时候可以得到这个执行结果,换句话说就是不知道这个结果什么时候是正确的,我们不得不每时每刻的去检查这个线程的执行结果。不过c++11中添加了对异步编程的支持,我们可以通过std::future获取我们关心的执行结果,虽然没有java中的异步操作丰富强大,但是对c++开发者来说已经方便了很多了。
     与之相关的有std::promise, std::package_task,std::future, std::shared_future,std::async()等
     Promise 对象可以保存某一类型的值,该值可被 future 对象读取(可能在另外一个线程中),因此 promise 也提供了一种线程同步的手段。在 promise 对象构造时可以和一个共享状态(通常是std::future)相关联,并可以在相关联的共享状(std::future)上保存一个类型为 T 的值。可以通过 get_future 来获取promise 对象相关联的 future 对象,调用该函数之后,两个对象共享相同的共享状态(shared state)。promise 对象是异步 Provider(提供者,可以理解为工厂),它可以在某一时刻设置共享状态的值。future 对象可以异步返回共享状态的值,或者在必要的情况下阻塞调用者并等待共享状态标志变为 ready,然后才能获取共享状态的值。下面看一个简单的例子

#include 
  
  
   
          // std::cin, std::cout, std::ios
#include 
   
   
    
         // std::ref
#include 
    
    
     
              // std::thread
#include 
     
     
      
               // std::promise, std::future
#include 
      
      
        // std::exception, std::current_exception void task(std::promise 
       
         & prom) { int x = 0; /* * 这里一般一个非常耗时耗cpu的操作如查找,计算等,在此过程中得到x的最终值,这里我们直接赋值为10 */ x = 10; prom.set_value(10); //设置共享状态的值,同时promise会设置为ready } void print_int(std::future 
        
          & fut) { int x = fut.get(); //如果共享状态没有设置ready,调用get会阻塞当前线程 std::cout << "value: " << x << '\n'; } int main () { std::promise 
         
           prom; // 生成一个 std::promise 
          
            对象. std::future 
           
             fut = prom.get_future(); // 和 future 关联. std::thread th1(task, std::ref(prom)); // 将 prom交给另外一个线程t1 注:std::ref,promise对象禁止拷贝构造,以引用方式传递 std::thread th2(print_int, std::ref(fut)); // 将 future 交给另外一个线程t. /* *主线程这里我们可以继续做一大堆我们想做的事,不用等待耗时的task线程,也不会因为等待task的执行结果而阻塞 */ th1.join(); th2.join(); return 0; } 
            
           
          
         
        
      
     
     
    
    
   
   
  
  

      std::packaged_task 包装一个可调用的对象,并且允许异步获取该可调用对象产生的结果,从包装可调用对象意义上来讲,std::packaged_task将其包装的可调用对象的执行结果传递给一个 std::future 对象(该对象通常在另外一个线程中获取 std::packaged_task 任务的执行结果)。std::packaged_task 对象内部包含了两个最基本元素,一、被包装的任务(stored task),任务(task)是一个可调用的对象,如函数指针、成员函数指针或者函数对象,二、共享状态(shared state),用于保存任务的返回值,可以通过 std::future 对象来达到异步访问共享状态的效果。可以通过 std::packged_task::get_future 来获取与共享状态相关联的 std::future 对象。在调用该函数之后,两个对象共享相同的共享状态,具体解释如下:std::packaged_task 对象是异步Provider,它在某一时刻通过调用被包装的任务来设置共享状态的值。std::future 对象是一个异步返回对象,通过它可以获得共享状态的值,当然在必要的时候需要等待共享状态标志变为 ready.
    
#include 
  
  
   
   
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      

int countdown (int from, int to) {
    for (int i=from; i!=to; --i) {
        std::cout << i << '\n';
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    std::cout << "Finished!\n";
    return from - to;
}

int main ()
{
    std::packaged_task
      
      
        task(countdown); // 设置 packaged_task std::future 
       
         ret = task.get_future(); // 获得与 packaged_task 共享状态相关联的 future 对象. std::thread th(std::move(task), 10, 0); //创建一个新线程完成计数任务. int value = ret.get(); // 等待任务完成并获取结果. std::cout << "The countdown lasted for " << value << " seconds.\n"; th.join(); return 0; } 
        
      
     
     
    
    
   
   
  
  

     这里我们可以看到两者的区别,创建线程时,上面传的是一个函数,这里却是一个package_task对象,它实际上做了简单的封装,简化了future的使用方法。当然还有更简单的写法就是用std::async来创建future:future<T> myFuture=async(task,10),在task中操作后,通过myFuture获取执行结果,我们甚至不用手动的创建线程,编译器会帮我们自动创建一个线程去执行。
    shared_future和future的区别是:一个future对象和一个共享状态相关,且转移只能通过move语义。但是多个shared_future对象可以和共享状态相关(即多对一)。std::shared_future 与 std::future 类似,但是 std::shared_future 可以拷贝、多个 std::shared_future 可以共享某个共享状态的最终结果(即共享状态的某个值或者异常)。shared_future 可以通过某个 std::future 对象隐式转换(参见 std::shared_future 的构造函数),或者通过 std::future::share() 显示转换,无论哪种转换,被转换的那个 std::future 对象都会变为 not-valid.
      
   以上只是一些最基本的用法,总 的看来还没有boost库的异步库,java异步接口等功能强大,更全面更详细的介绍看下面的参考资料,我也是个菜鸟。

    参考资料:

     http://blog.csdn.net/liuxuejiang158blog/article/details/17354115

     http://www.cplusplus.com/reference/future/

     https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/

     http://www.2cto.com/kf/201609/548243.html




    

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值