首页 > 编程语言 >开发者笔记 C++11新特性并发编程future

开发者笔记 C++11新特性并发编程future

时间:2023-10-12 12:11:56浏览次数:44  
标签:11 std get C++ future promise async include

上一篇介绍了<thread>文件里线程相关类,这篇将介绍C++ <future>头文件里线程类,future里包含的类主要是处理异步任务,线程函数封装,线程间通信,同步,捕捉异常处理 https://zhuanlan.zhihu.com/p/509118687

future的引入

c++11引入的future是为了解决异步通信问题的。future可以看做是数据通道,可以获取到async的线程函数的返回结果,也可以与promise连用,获取promise的数据。

举个例子来说明,在C++11之前我们在线程A中创建子线程B,为了拿到B中计算的数据,我们声明一个全局变量保存B的计算结果数据,线程A等待,直到B计算完成后,读取全局变量,拿到计算结果数据。C++11之后,我们可以声明future通过get方法获取异步返回值,很大程度的简化了操作步骤

future 只支持移动语义,不支持拷贝构造语义. 只允许一个future对象有权限获取结果

// future example
#include <iostream>       // std::cout#include <future>         // std::async, std::future#include <chrono>         // std::chrono::milliseconds
// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
  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); 

  // do something while waiting for function to set future:
  std::cout << "checking, please wait";
  std::chrono::milliseconds span (100);
  while (fut.wait_for(span)==std::future_status::timeout)
    std::cout << '.' << std::flush;

  bool x = fut.get();     // retrieve return value

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

  return 0;
}

shared_future

shared_future类似future, 但可以支持多线程同步,等待信号状态,类似条件变量的notify all

shared_future支持拷贝构造及移动,允许有多个对象监听状态,因此可以支持拷贝

#include <iostream>#include <future>#include <chrono> 
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";
}

std::async 异步函数,返回feature类对象

异步操作传入执行函数,参数信息,返回future类对象,std::future = std::async(fun, parm1, param2);

#include <iostream>#include <vector>#include <algorithm>#include <numeric>#include <future>#include <string>#include <mutex> 
std::mutex m;
struct X {
    void foo(int i, const std::string& str) {
        std::lock_guard<std::mutex> lk(m);
        std::cout << str << ' ' << i << '\n';
    }
    void bar(const std::string& str) {
        std::lock_guard<std::mutex> lk(m);
        std::cout << str << '\n';
    }
    int operator()(int i) {
        std::lock_guard<std::mutex> lk(m);
        std::cout << i << '\n';
        return i + 10;
    }
};
 
template <typename RandomIt>
int parallel_sum(RandomIt beg, RandomIt end)
{
    auto len = end - beg;
    if (len < 1000)
        return std::accumulate(beg, end, 0);
 
    RandomIt mid = beg + len/2;
    auto handle = std::async(std::launch::async,
                             parallel_sum<RandomIt>, mid, end);
    int sum = parallel_sum(beg, mid);
    return sum + handle.get();
}
 
int main()
{
    std::vector<int> v(10000, 1);
    std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
 
    X x;
    // Calls (&x)->foo(42, "Hello") with default policy:
    // may print "Hello 42" concurrently or defer execution
    auto a1 = std::async(&X::foo, &x, 42, "Hello");
    // Calls x.bar("world!") with deferred policy
    // prints "world!" when a2.get() or a2.wait() is called
    auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!");
    // Calls X()(43); with async policy
    // prints "43" concurrently
    auto a3 = std::async(std::launch::async, X(), 43);
    a2.wait();                     // prints "world!"
    std::cout << a3.get() << '\n'; // prints "53"
} // if a1 is not done at this point, destructor of a1 prints "Hello 42" here

promise

与future的关系示例图

promise类用于线程间通信用的,可以设置value, 通过future获取value.

通过get_future可以获取future对象

使用实例如下:

#include <vector>#include <thread>#include <future>#include <numeric>#include <iostream>#include <chrono> 
void accumulate(std::vector<int>::iterator first,
                std::vector<int>::iterator last,
                std::promise<int> accumulate_promise)
{
    int sum = std::accumulate(first, last, 0);
    accumulate_promise.set_value(sum);  // Notify future
}
 
void do_work(std::promise<void> barrier)
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    barrier.set_value();
}
 
int main()
{
    // Demonstrate using promise<int> to transmit a result between threads.
    std::vector<int> numbers = { 1, 2, 3, 4, 5, 6 };
    std::promise<int> accumulate_promise;
    std::future<int> accumulate_future = accumulate_promise.get_future();
    std::thread work_thread(accumulate, numbers.begin(), numbers.end(),
                            std::move(accumulate_promise));
 
    // future::get() will wait until the future has a valid result and retrieves it.
    // Calling wait() before get() is not needed
    //accumulate_future.wait();  // wait for result
    std::cout << "result=" << accumulate_future.get() << '\n';
    work_thread.join();  // wait for thread completion
 
    // Demonstrate using promise<void> to signal state between threads.
    std::promise<void> barrier;
    std::future<void> barrier_future = barrier.get_future();
    std::thread new_work_thread(do_work, std::move(barrier));
    barrier_future.wait();
    new_work_thread.join();
}

packaged_task

这个类是线程函数的封装,包括lambda, funtion, function object, bind expression. 与promise一样可以获取异步返回值,通过get_future函数获取future对象

// packaged_task example
#include <iostream>     // std::cout#include <future>       // std::packaged_task, std::future#include <chrono>       // std::chrono::seconds#include <thread>       // std::thread, std::this_thread::sleep_for
// count down taking a second for each value:
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 << "Lift off!\n";
  return from-to;
}

int main ()
{
  std::packaged_task<int(int,int)> tsk (countdown);   // set up packaged_task
  std::future<int> ret = tsk.get_future();            // get future

  std::thread th (std::move(tsk),10,0);   // spawn thread to count down from 10 to 0

  // ...

  int value = ret.get();                  // wait for the task to finish and get result

  std::cout << "The countdown lasted for " << value << " seconds.\n";

  th.join();

  return 0;
}

 

参考:

  • cplusplus
  • cppreference
  • Effective modern c++

标签:11,std,get,C++,future,promise,async,include
From: https://www.cnblogs.com/tomato-haha/p/17759204.html

相关文章

  • C++11新特性之基本范围的For循环(range-based-for)
    C++11新特性之基本范围的For循环(range-based-for)最新推荐文章于 2023-07-2219:30:58 发布Rayen0715于2017-01-0713:49:35发布49588收藏174版权Range-Based-For熟悉C++98/......
  • 10.11
    又是运气爆表的一天!8.10切A,线段树板子看了一眼发现B有点像贪心,但是不太会,开C9.40切C换根板子,并且考过回去看B,想了想会了10.50切B打了个T4的暴力+剪枝检查跑路应得分数400=100+100+100+80实得分数372=100+92+100+80最高分400=100+100+100+100......
  • C++异步定时器设计与实现
    C++异步定时器设计与实现由于目前C++标准中没有现成的定时器,本设计使用C++11相关语法并进行封装。本定时器包含一个TimerManager类用于创建定时器和进行定时任务管理,TimerManager会创建两个线程(mTimerTickThread、mTimerCallbackThread)分别用于时间处理和函数回调。可以使用Ti......
  • 11. 用Rust手把手编写一个wmproxy(代理,内网穿透等), 实现健康检查
    11.用Rust手把手编写一个wmproxy(代理,内网穿透等),实现健康检查项目++wmproxy++gite:https://gitee.com/tickbh/wmproxygithub:https://github.com/tickbh/wmproxy健康检查的意义健康检查维持着系统的稳定运行,极大的加速着服务的响应时间,并保证服务器不会把消息包转......
  • 10.11总结
    1.解决了好几个报错①数据库表设置自增,在application.properties中mybatiesplus中要写id_type=auto,实现不写入id数据,数据库进行自增操作②没写注释@Autowired导致的一系列错误③mapper映射找不到,包对不上忽略一个问题就是创建包的时候要用com/example/mapper而不是com.example.......
  • 1011打卡
    1.串联所有单词的子串(30) 思想:哈希表+滑动窗口classSolution{publicList<Integer>findSubstring(Strings,String[]words){intlen=words.length;intwordlen=words[0].length();HashMap<String,Integer>map=newHashMap<>......
  • 每日总结20231011
    代码时间(包括上课)3h代码量(行):100行博客数量(篇):1篇相关事项:1、今天是周三,今天上午上的是软件构造,软件构造讲的是程序规范化。2、今天下午我们进行了献血的演讲的观看,明白了献血的意义。3、今天还打算看看软件设计师相关的题目,我要过,我要通过,我要高分通过!......
  • 20231011
    //eclectic,extreme,halfway,medium,request,tradeoff,giveground,meanmethod,middleway,midwaypoint,strikeahappymediumeclectic-折中的,多元的Eclecticreferstoastyleorapproachthatcombineselementsorideasfromvarioussourcesorstyles.......
  • 144-11
    给定二叉树,删除结点值为x的左右子树利用层次遍历找到结点值为x的左右子树,分别删除;删除算法voidDelete(Tree&T){if(T){Delete(T->lchild);Delete(T->rchild);free(T);}}完整算法#include<stdio.h>#include<stdlib.h>#d......
  • Effective C++ 笔记-1.1视C++为一个语言联邦
    应当这样正确的看待C++语言,将C++视为一个由相关次语言组成的联邦,而非单一语言。每种次语言都有自己的守则,当你从一个次语言移向另一个次语言,守则可能改变。其主要的次语言总共有4个:C:Object-OrientedC++;TemplateC++:STL:******C++高效编程守则视状况而变化,取决于你使用C+......