C++:并发与多线程(十)

一 原子操作 std:atomic续谈

不是所有运算符都支持 比如不支持 a = a+1

二 std: async深入谈

2.1 std: async参数详述

std::thread() 如果系统资源紧张,可能会创建线程失败,执行std::thread()时程序可能会崩溃。
std::async 一般称之为创建一个异步任务,async有时并不创建新线程
如果用std::launch::deferred来调用async会怎么样,会延迟调用,并且不创建新线程,如果future不调用.wait或.get,则不执行async的入口函数
如果用std::launch::async 强制这个异步任务在新线程上执行,系统必须创建新线程。
std::launch::async |std::launch::deferred 当参数是这样时,意味着async的行为可能是其中任意一个,由编译器实现
当不传入参数时,默认参数为std::launch::async |std::launch::deferred,具体使用哪个由编译器控制。

#include <iostream>
#include <string>
#include <future>
#include <thread>
#include <mutex>
#include <atomic>
using namespace  std;

int mythread()
{
    cout<<"mythread start"<<"thread_id:"<<std::this_thread::get_id<<endl;
    return 1;
}


int main()
{
     cout<<"main thread_id:"<<std::this_thread::get_id<<endl;
    std::future<int>result = std::async(std::launch::deferred,mythread);
    cout<<result.get()<<endl;
    cout<<"ok"<<endl;
    return 0;

}

打印:

G:\CSlrn\C++Code\MultiThread\2_11\cmake-build-debug\2_11.exe
main thread_id:1
mythread startthread_id:1
1
ok

Process finished with exit code 0

2.2 std: async和std: thread的区别

  • std::thread创建线程,如果系统资源紧张,创建线程失败,那么整个程序就会报异常并崩溃
  • std::thread创建线程,如果线程有返回值,不方便拿到该返回值
  • std::async创建异步任务,可能创建线程,也可能不创建线程,并且该方法很容易拿到线程入口函数的返回值。
    由于系统资源限制
  • (1)如果std::thread创建的线程太多,则可能创建失败,系统报告异常
  • (2)std::async一般不会异常,如果系统资源紧张时,不加额外参数的async就不会创建新线程,而是后续谁调用了result.get来请求结果,那么这个异步任务就会运行在调用get语句的线程中执行。
  • (3)一个程序里,线程数量不宜超过100-200

2.3 std async不确定性问题的解决

  • 不加额外参数的std::async调用,让系统自行决定是否创建新线程
  • 问题焦点:std::futureresult2 = std::async(mythread);这个写法
  • 这个异步任务到底有没有被推迟执行 ,使用上节课的wait_for语句可以判断
int mythread()
{
    cout<<"mythread start"<<"thread_id:"<<std::this_thread::get_id<<endl;
    std::chrono::seconds dura(5);
    std::this_thread::sleep_for(dura);
    return 1;
}
 cout<<"main thread_id:"<<std::this_thread::get_id<<endl;

    std::future<int>result = std::async(std::launch::deferred,mythread);
    std::future_status status = result.wait_for(std::chrono::seconds(2));
    if (status == std::future_status::timeout)
    {
        //线程没有被推迟 但是还没执行完
        cout<<"time out"<<endl;
    }
    else  if (status == std::future_status::ready)
    {
        //线程没有被推迟,并且执行完了
        cout<<"thread over"<<endl;
    }
    else  if (status == std::future_status::deferred)
    {
        //线程被延迟了,需要由result.get()来启动线程
        cout<<"thread deferred"<<endl;
        result.get();
    }
    cout<<"ok"<<endl;
    return 0;
G:\CSlrn\C++Code\MultiThread\2_11\cmake-build-debug\2_11.exe
main thread_id:1
thread deferred
mythread startthread_id:1
ok

Process finished with exit code 0

在代码调试中,当我们把额外参数设置为std::launch::async时,分别打印主线程id和子线程id,发现id是一样的,那么我们要判断是否启动了子线程,除了用wait_for函数来判断,我们还可以用延时语句来判断,比如下面这个例子

线程入口函数没延迟5s再打印线程id

int mythread()
{

    std::chrono::seconds dura(5);
    std::this_thread::sleep_for(dura);
    cout<<"mythread start"<<"thread_id:"<<std::this_thread::get_id<<endl;
    return 1;
}

main函数中,等待5s再执行reslut.get(),此时参数为deferred,可以预料到,当主线程等待5s后才会执行子线程,运行起来后,可以大概数一下秒数。

 cout<<"main thread_id:"<<std::this_thread::get_id<<endl;

    std::future<int>result = std::async(std::launch::deferred,mythread);
    std::chrono::seconds dura(5);
    std::this_thread::sleep_for(dura);
    cout<<"result="<<result.get()<<endl;
    cout<<"ok"<<endl;
    return 0;

结果就是在打印完主线程id后,10s过后才会打印子线程id,打印reslut,打印ok,说明系统是没有创建子线程的。

G:\CSlrn\C++Code\MultiThread\2_11\cmake-build-debug\2_11.exe
main thread_id:1
mythread startthread_id:1
result=1
ok

Process finished with exit code 0

如果我们将参数改为std::launch::async,由std::launch::async的异步性可以知道,一创建std::async就会启动子线程,子线程内等待的5s和主线程内等待的5s几乎是同时开始计时的,所以总共只需要5s就会打印子线程id和reslut ,以及ok,我们就可以判断,std::launch::async确实创建了子线程

G:\CSlrn\C++Code\MultiThread\2_11\cmake-build-debug\2_11.exe
main thread_id:1
mythread startthread_id:1
result=1
ok

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Michael.Scofield

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值