C++ 异步编程(std::async、std::future、std::promise)

C++ 11 异步编程

std::thread (C++创建线程)

函数
thread() noexcept 创建一个线程,什么也不做
template <class Fn, class... Args>
explicit thread(Fn&& fn, Args&&... args) 创建一个线程,以args为参数,执行fn函数
thread(const thread&) = delete 复制购置函数
thread(thread&& x) noexcept 移动购置函数
~thread() 析构函数
void join() 等待线程结束并清理资源(会阻塞)
bool joinable() 返回线程是否可以joinable
void detach() 将线程与调用其的线程分离,彼此独立执行(此函数必须在线程创建时立即调用,且调用此函数会使其不能被join)
thread& operator=(thread &&rhs) 移动赋值函数

例子:

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
std::mutex mtx;
void thread_p(int a, int b)
{
	mtx.lock();
	cout <<"thread id:"<< std::this_thread::get_id()<< " a:" << a << "b: " << endl;
	mtx.unlock();
}
int main()
{
	std::thread t1(thread_p, 1,2), t2(thread_p, 3,4);
	cout << "t1.joinabel(): " << t1.joinable()<<endl;
	t1.join();
	cout << "t1.joinabel(): " << t1.joinable() << endl;

	t2.detach();
	cout << "t2.joinabel(): " << t2.joinable() << endl;
	return 0;
}

运行结果:

std::future

thread对象,它是C++11中提供异步创建多线程的工具。但是我们想要从线程中返回异步任务结果,一般需要依靠全局变量;从安全角度看,有些不妥;为此C++11提供了std::future类模板,future对象提供访问异步操作结果的机制,很轻松解决从异步任务中返回结果。

参考
https://en.cppreference.com/w/cpp/thread/future

函数 解释
void wait() const; 等待值返回
template< class Rep, class Period >std::future_status wait_for( const std::chrono::duration<Rep,Period>& timeout_duration ) const; 等待多长时间
template< class Clock, class Duration >std::future_status wait_until( const std::chrono::time_point<Clock,Duration>& timeout_time ) const; 等待到多久之后返回
get 会一直阻塞直到拿到结果
bool valid() const noexcept; 检查 future 是否引用共享状态。
cpp 复制代码
#include <iostream>
#include <future>
#include <thread>
using namespace std;
int main()
{
    std::future<int> f;
    cout << f.valid() << endl;

	std::future<int> v = std::async([] {std::this_thread::sleep_for(std::chrono::milliseconds(1000)); return 8; });
    std::future_status status = v.wait_for(std::chrono::microseconds(2000));
    switch (status)
    {
    case std::future_status::deferred:
        std::cout << "deferred\n";
        break;
    case std::future_status::timeout:
        std::cout << "timeout\n";
        break;
    case std::future_status::ready:
        std::cout << "ready!\n";
        break;
    }

	
	cout << v.valid() << endl;
	cout << v.get() << endl;
	cout << v.valid() << endl;
	return 0;
}

std::promise

std::promise 是C++11并发编程中常用的一个类,常配合std::future使用。其作用是在一个线程t1中保存一个类型typename T的值,可供相绑定的std::future对象在另一线程t2中获取。
https://en.cppreference.com/w/cpp/thread/promise

函数
get_future 获取一个futrue对象
set_value 设置值
cpp 复制代码
#include <iostream>
#include <future>

void thread1(std::promise<int> &p)
{

	std::this_thread::sleep_for(std::chrono::milliseconds(500));
	std::cout << "thread1 set data" << std::endl;
	p.set_value(1);
}

void thread2(std::future<int>& p)
{
	int data = p.get();
	std::cout << "thead2 read data:" <<data << std::endl;
}
int main()
{
	using namespace std;
	std::promise<int> p;
	std::future<int> f = p.get_future();
	std::thread t1(thread1, std::ref(p));
	std::thread t2(thread2, std::ref(f));
	t1.join();
	t2.join();
	return 0;
}

结果:

std::async

由于std::thread不能很方便的获取线程运行完之后的返回值
https://en.cppreference.com/w/cpp/thread/async

template< class F, class... Args >/* see below */ async( F&& f, Args&&... args ); 立即执行
template< class F, class... Args >/* see below */ async( std::launch policy, F&& f, Args&&... args ); 可以设置延迟和立即执行状态
std::launch::async 立即执行
std::launch::deferred 延迟执行

不接收返回值会先阻塞

不接收放回值相当于std::thread语句后面立即join会阻塞当前线程执行完然后执行下一个线程。

cpp 复制代码
#include <iostream>
#include <thread>
#include <future>
using namespace std;

int main()
{
	
	std::async([] {
		for (int i = 0; i < 5; i++)
		{
			cout << "thead 1:" << i<< endl;
		}
		
		});

	std::async([] {
		for (int i = 0; i < 5; i++)
		{
			cout << "thead 2:" << i << endl;
		}

		});
	return 0;
}

接收返回值才不会直接阻塞

cpp 复制代码
#include <iostream>
#include <thread>
#include <future>
using namespace std;

int main()
{
	
	std::future<void> r1=  std::async([] {
		for (int i = 0; i < 5; i++)
		{
			cout << "thead 1:" << i<< endl;
		}
		
		});

	std::async([] {
		for (int i = 0; i < 5; i++)
		{
			cout << "thead 2:" << i << endl;
		}

		});
	return 0;
}

std::launch::deferred 延迟加载

只有当wait、get结果才会执行

cpp 复制代码
#include <iostream>
#include <thread>
#include <future>
using namespace std;

int main()
{
	
	std::future<void> r1=  std::async(std::launch::deferred,[] {
		for (int i = 0; i < 5; i++)
		{
			cout << "thead 1:" << i<< endl;
		}
		
		});

	std::async([] {
		for (int i = 0; i < 5; i++)
		{
			cout << "thead 2:" << i << endl;
		}

		});
	return 0;
}
cpp 复制代码
#include <iostream>
#include <thread>
#include <future>
using namespace std;

int main()
{
	
	std::future<void> r1=  std::async(std::launch::deferred,[] {
		for (int i = 0; i < 5; i++)
		{
			cout << "thead 1:" << i<< endl;
		}
		
		});

	std::async([] {
		for (int i = 0; i < 5; i++)
		{
			cout << "thead 2:" << i << endl;
		}

		});
	r1.get();
	return 0;
}

总结

std::future 一个未来值,可以先赋值,来源可以是std::promise的set_value之后,或者是std::async的返回值
std::promise 和std::future结合可以从一个线程中回去另一个线程的值。
std::async 创建线程、需要获取返回值std::future对象,不然会直接阻塞。并且可以指定,std::launch::async立即执行std::launch::deferred延迟执行,延迟执行只有wait future对象或get future对象的之后才会执行
相关推荐
YuforiaCode3 分钟前
第十二届蓝桥杯 2021 C/C++组 直线
c语言·c++·蓝桥杯
我真的不会C8 分钟前
QT窗口相关控件及其属性
开发语言·qt
CodeCraft Studio8 分钟前
Excel处理控件Aspose.Cells教程:使用 Python 在 Excel 中进行数据验
开发语言·python·excel
火柴盒zhang14 分钟前
websheet之 编辑器
开发语言·前端·javascript·编辑器·spreadsheet·websheet
景天科技苑21 分钟前
【Rust】Rust中的枚举与模式匹配,原理解析与应用实战
开发语言·后端·rust·match·enum·枚举与模式匹配·rust枚举与模式匹配
阿让啊26 分钟前
C语言中操作字节的某一位
c语言·开发语言·数据结构·单片机·算法
椰羊~王小美32 分钟前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
草莓啵啵~1 小时前
搜索二叉树-key的搜索模型
数据结构·c++
共享家95271 小时前
深入理解C++ 中的list容器
c++
孞㐑¥1 小时前
C++11介绍
开发语言·c++·经验分享·笔记