1、std::thread与std::async对比
1.1、std::thread介绍
- std::thread是C++11中提供的创建线程的一个手段,它是在
<thread>
头文件中,它的返回值是一个线程主体对象,主要提供下面几个函数- join:调用该指令所在的线程阻塞,等待被调用线程的执行完毕
- detach:调用该指令所在的线程与被调用线程分离,无须管理被调用线程的生死
- joinable:判断线程是否可以join和detach,因为这两个方法只能调用一次
- native_handle:获得句柄,应该是线程执行的入口函数
- get_id:获取线程id
- 还有一些swap和赋值=重载,都是用于移交线程的管理权
std::thread的部分源码解析点击这里
1.2、std::async介绍
- std::async是C++11中提供的创建异步任务的一个方法,它是在
<future>
头文件中,它的返回值是一个future对象,通过future主要提供下面几个函数- get:获取异步任务的返回值,future模板类下该值只能获取一次,shared_future模板类下该值能重复获取
- valid:判断是否可以获得异步任务的返回值
- wait:阻塞等待该异步任务的执行,没有返回值
- wait_for:等待该任务一个指定的时间长度,可以获取到线程的状态(ready、timeout、deferred)
- wait_until:等待该任务到一个指定的时间点,可以获取到线程的状态(ready、timeout、deferred)
- share:返回一个shared_future对象
- 还有赋值=重载,都是用于移交异步任务的管理权
std::async的部分源码解析点击这里
1.3、对比
- std::thread用于创建一个线程,这个线程是一定会被创建的,如果系统资源紧张,强行创建会导致系统的崩溃
- std::async用于创建一个异步任务,这个任务不一定会被创建,需要根据标记和实际情况决定
- std::launch::async:强制立即创建这个异步任务,并且自动执行
- std::launch::deferred:延迟创建这个异步任务,等待get或wait系列函数的调用在创建,如果不调用就不创建。
- std::launch::async | std::launch::deferred:这个值为3(async = 1,deferred = 2),传入这两个混合标记就需要看编译器怎么决定了。Linux下或默认传入std::launch::async | std::launch::deferred),然后&std::launch::async,实际上就是立即创建。
- 不传入标记:根据编译器的情况进行判断是否需要创建,情况同上
- 当系统资源紧张时:
- std::thread还是一样强行创建,可能会导致系统报告异常,程序崩溃停止
- std::async会根据系统的实际情况判断是否需要创建,async立即创建,deferred延迟等待调用时创建(实际并不创建,会在调用get或wait函数的地方)直接串行执行,即在调用的线程里做到(等价于把线程函数入口移交到调用的地方)
#include <iostream>
#include <thread>
#include <future>
int thread_func()
{
std::cout << __func__ << " 开始执行! thread_id =" << std::this_thread::get_id() << std::endl;
std::chrono::milliseconds duration(5000);
std::this_thread::sleep_for(duration);
std::cout << __func__ << " 执行完毕! thread_id =" << std::this_thread::get_id() << std::endl;
return 5;
}
void async_test1()
{
std::cout << "main thread_id = " << std::this_thread::get_id() << std::endl;
std::future<int> async_result = std::async(std::launch::deferred, thread_func);
std::cout << "continue......" << std::endl;
std::cout << async_result.get() << std::endl;
}
/*
由于deffered是延迟创建,因此主线程在执行完之后调用get会导致两个线程串行,最后子线程不会new出来, 由主线程执行!
main thread_id = 140214074877760
continue......
thread_func 开始执行! thread_id =140214074877760
thread_func 执行完毕! thread_id =140214074877760
5
*/
void async_test2()
{
std::cout << "main thread_id = " << std::this_thread::get_id() << std::endl;
std::future<int> async_result = std::async(std::launch::deferred, thread_func);
std::cout << "continue......" << std::endl;
}
/*
没有调用get,不进行执行。但是可能在析构的时候会调用get或者wait执行,这个需要看编译器的情况来定,上面没有看到析构
main thread_id = 139630206793536
continue......
*/
int main() {
//async_test1();
async_test2();
std::cout << "Hello, World!" << std::endl;
return 0;
}