首页 > 编程语言 >C++之future

C++之future

时间:2023-07-01 12:44:38浏览次数:37  
标签:std 异步 C++ future promise result 操作

背景

在C++多线程编程中,同步线程间的操作和结果通常是一个关键问题。C++11引入了std::future这一同步原语,用于表示异步操作的结果。本文将介绍C++中std::future的使用方法、优势以及与其他同步方法的对比。

使用std::future

std::future表示一个异步操作的结果,可以用于获取操作的返回值或者等待操作完成。std::future通常与std::async、std::packaged_task或std::promise一起使用。

使用std::async

std::async是一个简单的异步操作启动器,它接受一个函数及其参数,并在一个新线程中执行该函数。std::async返回一个std::future对象,用于表示异步操作的结果。

#include <iostream>
#include <future>
#include <chrono>

int slow_operation() {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    return 42;
}

int main() {
    std::future<int> result = std::async(slow_operation);
    std::cout << "Waiting for the result..." << std::endl;
    int value = result.get();
    std::cout << "Result: " << value << std::endl;
    return 0;
}

在这个示例中,我们使用std::async启动一个慢速操作slow_operation。std::async返回一个std::future对象,我们可以使用get()方法等待操作完成并获取结果。

使用std::packaged_task

std::packaged_task是一个通用的异步操作包装器,它接受一个函数并将其包装成一个任务。我们可以将任务传递给一个线程执行,然后使用std::future来表示任务的结果。

#include <iostream>
#include <future>
#include <thread>

int slow_operation() {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    return 42;
}

int main() {
    std::packaged_task<int()> task(slow_operation);
    std::future<int> result = task.get_future();
    std::thread t(std::move(task));
    std::cout << "Waiting for the result..." << std::endl;
    int value = result.get();
    std::cout << "Result: " << value << std::endl;
    t.join();
    return 0;
}

在这个示例中,我们使用std::packaged_task包装一个慢速操作slow_operation,然后将任务传递给一个线程执行。我们使用get_future()方法获取一个std::future对象,用于表示任务的结果。

使用std::promise

std::promise是一个低级别的异步操作同步原语,它允许我们在一个线程中设置操作的结果,并在另一个线程中等待该结果。std::promise与std::future一起使用,用于表示操作的结果。

#include <iostream>
#include <future>
#include <thread>

void slow_operation(std::promise<int> result_promise) {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    result_promise.set_value(42);
}

int main() {
    std::promise<int> result_promise;
    std::future<int> result = result_promise.get_future();
    std::thread t(slow_operation, std::move(result_promise));
    std::cout << "Waiting for the result..." << std::endl;
    int value = result.get();
    std::cout << "Result: " << value << std::endl;
    t.join();
    return 0;
}

在这个示例中,我们使用std::promise在slow_operation函数中设置操作的结果。我们使用get_future()方法获取一个std::future对象,用于表示操作的结果。

std::future的优势

相较于其他同步方法,如互斥锁(std::mutex)和条件变量(std::condition_variable),std::future具有以下优势:

  • 简化编程模型:std::future简化了线程间结果传递的编程模型,使得我们可以更容易地编写正确的并发代码。
  • 自动同步:std::future在获取结果时自动实现同步,无需显式地使用互斥锁或条件变量。
  • 异常安全:std::future可以在异步操作中捕获异常,并在获取结果时重新抛出,从而确保异常安全。

使用场景与比较

std::future适用于以下场景:

  • 需要在线程间传递结果的异步操作。

  • 需要等待异步操作完成的场景。

  • 需要捕获异步操作中的异常。 相较于其他同步方法,std::future具有更简洁的编程模型和更好的异常安全性。然而,在某些场景下,互斥锁和条件变量可能更适合,例如:

  • 需要保护复杂数据结构的访问。

  • 需要在线程间传递通知的场景(如生产者消费者队列)。

最后

总结一下,在这篇博客中,我们介绍了C++并发操作同步中的std::future,包括使用std::async、std::packaged_task和std::promise进行异步操作,以及std::future的优势和使用场景。std::future是一种强大的同步原语,可以帮助我们简化多线程编程中的同步问题。在实际应用中,我们需要根据具体的需求和场景选择合适的同步方法,以实现高效、稳定的多线程程序。

 

标签:std,异步,C++,future,promise,result,操作
From: https://www.cnblogs.com/blizzard8204/p/17519127.html

相关文章

  • Qt/C++编写超精美自定义控件(历时9年更新迭代/超202个控件/祖传原创)
    一、前言无论是哪一门开发框架,如果涉及到UI这块,肯定需要用到自定义控件,越复杂功能越多的项目,自定义控件的数量就越多,最开始的时候可能每个自定义控件都针对特定的应用场景,甚至里面带了特定的场景的一些设置和处理,随着项目数量的增多,有些控件又专门提取出来共性,做成了通用的自定义......
  • 【零基础学习C++】如何写一个C++类?
    个人主页:【......
  • 《Linux C/C++ 服务器开发实践》记录
    《LinuxC/C++服务器开发实践》记录序言:该记录是一份读书笔记,因为主题需要和计算机操作系统有关,自然而然的想到Linux的学习,刚好最近找实习发现很多C++服务器方向需要熟悉Windows/Linux的多线程开发,所以就选了这本《LinuxC/C++服务器开发实践》来看,这本书有许多工作用得上的知......
  • C++面试八股文:什么是空指针/野指针/悬垂指针?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第30面:面试官:什么是空指针?二师兄:一般我们将等于0/NULL/nullptr的指针称为空指针。空指针不能被解引用,但是可以对空指针取地址。int*p=nullptr; //空指针*p=42; //空指针不可以解引用int**pp=&p //空指针可以取地址......
  • C++面试八股文:std::vector了解吗?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第23面:面试官:vector了解吗?二师兄:嗯,用过。面试官:那你知道vector底层是如何实现的吗?二师兄:vector底层使用动态数组来存储元素对象,同时使用size和capacity记录当前元素的数量和当前动态数组的容量。如果持续的push_back(empl......
  • 【c++基础】位域结构体
    前言code#include<iostream>typedefstruct{unsignedinta:5;unsignedintb:3;}tBits;intmain(){tBitsaa;aa.a=205;//11001101aa.b=89;//01011001std::cout<<"a:"<<aa.a<<......
  • CompletableFuture之批量上传
    前言最近接到一个需求,批量上传图片到服务器及实时更新上传进度。当处理大量文件上传任务时,效率是一个关键因素。传统的串行方式会导致任务耗时较长,而使用并发处理可以极大地提高上传效率。想到很久之前用CompletableFuture优化过一些多统计的业务场景,效果都还不错,因此在这里也使......
  • C++中三个特殊的宏 __FILE__, __FUNCTION__ 和 __LINE__
    有一次在看代码时,发现如下代码:m_strClassFileName=__FILE__;  把 __FILE__赋给了一个变量.这是我第一次接触__FILE__,于是查找了一下,才发现它是C++中三个特殊的宏之一.C++中共有三个特殊的宏,分别是 __FILE__,__FUNCTION__和__LINE__......
  • C++代码中字符串分多行时的情况
    #include<iostream>intmain(constintargc,constchar*argv[]){std::stringstrSql1="select*fromtable\whereid=1\andname='name'";std::cout<<strSql1<<std::endl;std::stringst......
  • C++面试八股文:什么是构造函数?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第29面:面试官:什么是构造函数?二师兄:构造函数是一种特殊的成员函数,用于创建和初始化类的对象。构造函数的名称与类的名称相同,并且没有返回类型。构造函数在对象被创建时自动调用。structFoo{Foo(intv):val(i){} //构造函数p......