栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++多线程学习(四)异步编程

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++多线程学习(四)异步编程

前面刚大写特写多线程同步,这里怎么又扯到异步编程了,嘿嘿,其时两者的'步'不是一个东西,前面讲的同步,是对于所访问资源的有序处理,此处就是在接口层面,是被调用方是否执行完毕才停止阻塞,需要等待执行完毕就是同步,否则就是异步。熟悉windows编程的同学很容易就联想到一个东西了,SendMessage、PostMessage,其机制,优势、缺陷网上有太多的资料了,有过相关编程经验的人也都清楚其是怎么回事了。那么,这里我们深入探讨下,他们到底是如何实现的呢?

同步这个不多说,顺序执行命令就是同步了,不需要额外处理什么,那么异步是如何实现的呢?首先我们看下异步的特点。

  • 接口被调用不阻塞,调用线程可以继续往下执行
  • 调用线程有方法可以获取到接口执行完毕的通知,并获取其返回值

 首先看接口不阻塞,代码内存肯定共用,这个不做他想,肯定是创建一个线程,来执行这个接口函数。再看下接口执行完毕通知调用线程,这个我们前面学的条件变量可以解决,这样一看异步接口也不是很复杂吗,看示例

//future1.cpp 使用全局变量传递被调用线程返回结果,使用条件变量通知调用线程已获得结果

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int res = 0;						//保存结果的全局变量
std::mutex mu;						//互斥锁全局变量
std::condition_variable cond;       //全局条件变量
 
void accumulate(std::vector::iterator first,
                std::vector::iterator last)
{
    int sum = std::accumulate(first, last, 0);      //标准库求和函数
    std::unique_lock locker(mu);
    res = sum;
    locker.unlock();
    cond.notify_one();              // 向一个等待线程发出“条件已满足”的通知
}
 
int main()
{
    std::vector numbers = { 1, 2, 3, 4, 5, 6 };
    std::thread work_thread(accumulate, numbers.begin(), numbers.end());

    std::unique_lock locker(mu);
    cond.wait(locker, [](){ return res;});   //如果条件变量被唤醒,检查结果是否被改变,为真则直接返回,为假则继续等待
    std::cout << "result=" << res << 'n';
    locker.unlock();
    work_thread.join();         //阻塞等待线程执行完成
 
    getchar();
    return 0;
}

引入了三个全局变量res、mu、cond,接口还被入侵,调用线程获取结果还要增加unique_lock,对于工程设计的破坏巨大。那么有没有优雅一点的接口可以实现相关功能呢?当然有,直接给出终极方案std::async接口。直接看例子

//future4.cpp 使用async传递被调用线程返回结果

#include 
#include 
#include 
#include 
#include 
#include 
 
int accumulate(std::vector::iterator first,
                std::vector::iterator last)
{
    int sum = std::accumulate(first, last, 0);
    return sum;
}
 
int main()
{
    // 演示用 async 在线程间传递结果。
    std::vector numbers = { 1, 2, 3, 4, 5, 6 };
    auto accumulate_future = std::async(std::launch::async, accumulate, numbers.begin(), numbers.end());		//auto可以自动推断变量的类型
    std::cout << "result=" << accumulate_future.get() << 'n';
 
    getchar();
    return 0;
}

std::async接口替我们完成了创建线程的过程,接口返回的std::future变量替换了前面三个全局变量的限制,std::future的get接口替我们完成了额外增加条件向量的尴尬。果然,优雅的尽头就是封装,不过了解封装之前的代码有助于我们更好的理解接口。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/630623.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号