C++多线程:std::thread与std::async对比(十一)

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;
}

  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值