现代 C++20 实战高手课
卢誉声
Autodesk 首席工程师
3781 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 29 讲
现代 C++20 实战高手课
15
15
1.0x
00:00/00:00
登录|注册

07|Coroutines背景:异步I/O的复杂性

你好,我是卢誉声。
在日常工作中,我们经常会碰到有关异步编程的问题。但由于绝大多数异步计算都跟 I/O 有关,因此在很多现代编程语言中,都支持异步编程,并提供相关的工具。
不过在 C++20 以前,异步编程从未在 C++ 语言层面得到支持,标准库的支持更是无从说起。我们往往需要借助其他库或者操作系统相关的编程接口,来实现 C++ 中的异步编程,特别是异步 I/O。比如 libuv、MFC,它们都提供了对消息循环和异步编程的支持。
接下来的三节课,我们主要讨论 C++ coroutines。这节课里,为了让你更好地理解 C++ coroutines,我们有必要先弄清楚同步与异步、并发与并行的概念以及它们之间的区别。同时,我还会跟你一起,通过传统 C++ 解决方案实现异步 I/O 编程,亲身体验一下这种实现的复杂度。这样后面学习 C++ coroutines 的时候,你更容易体会到它的优势以及解决了哪些棘手问题(课程配套代码,点击这里即可获取)。
好了,我们话不多说,先从基本概念开始讲起。

同步与异步

同步与异步的概念比较容易理解。所谓“同步”,指的是多个相关事务必须串行执行,后续事务需要等待前一事务完成后再进行。
我们日常使用的 iostream,本质上就是一种同步 I/O,在发起 I/O 任务后当前线程就会一直阻塞等待,直到当前任务完成后才会继续后续任务,同时不会处理其他的任务。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

C++20之前,C++语言并未官方支持异步编程,导致开发者需要借助其他库或操作系统接口来实现异步I/O。本文介绍了同步与异步、并发与并行的概念,并强调了异步系统在提升计算机资源利用率方面的优势。文章探讨了C++传统异步I/O实现方法,特别是使用C++11线程库来实现消息循环。通过讲解线程库的核心std::thread类,文章展示了如何创建线程对象并等待其执行结束。文章以简单的代码示例和图表形象地解释了异步编程的概念和实现方式,为后续讨论C++ coroutines奠定了基础。 文章还介绍了使用C++11提供的promise和future来获取函数的处理结果和异常信息,实现更精细化的线程同步和线程调度。此外,文章提到了线程池的重要性,指出线程池可以更充分地利用CPU的并行、并发能力,同时避免给系统带来不必要的负担。最后,文章提出了课后思考问题,鼓励读者结合promise、future和mutex来实现能够处理结构化异常的线程池。 总的来说,本文深入探讨了C++异步编程的基本概念和实现方式,为读者提供了全面的技术视角和实践思路。文章内容丰富,涵盖了异步编程的多个方面,对于想要深入了解C++异步编程的读者来说,是一篇具有很高参考价值的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《现代 C++20 实战高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(6)

  • 最新
  • 精选
  • Geek_7c0961
    同步, 异步, 阻塞, 非阻塞 这四个概念还是有必要区分清楚. 详见 https://www.cnblogs.com/lixinjie/p/a-post-about-io-clearly.html

    作者回复: :thumbup:

    2023-02-07归属地:美国
    2
  • 王子面
    "static void count(int32_t maxValue)"声明为静态的原因是什么?

    作者回复: C++里全局的static函数的意思是该符号仅对当前编译单元可见(internal linkage),防止各个编译单元之间符号因为链接性产生污染,这里我们项目只有一个编译单元,所以可加可不加。

    2023-10-02归属地:美国
  • 王子面
    “绝大多数异步计算都跟 I/O”的根本原因是什么?能不能举一两个跟I/O无关的异步计算的例子?

    作者回复: 异步是个很广泛的概念,比如主线程启动了子线程T1、T2和T3,使用子线程进行计算,但是自己先去完成其他的任务,一定时间之后再回来获取子线程的计算结果(或者通过其他方式告知主线程计算任务完成)。这个过程中,主线程并没有等待子线程计算结果,这个过程就是异步的,但又不是I/O任务。

    2023-10-02归属地:美国
  • Geek_6778f9
    “接着,我们在 main 函数中创建了三个异步任务,给每个任务分别创建对应的目录。这三个任务会同时启动并独立执行。我们在这些线程对象上调用 join,让主线程等待这三个线程结束。” 老师,这里主线程需要等待子线程执行结束,我理解这是同步编程,为什么是异步?

    作者回复: 这里主线程的确在同步等待三个任务,但是三个任务启动其实是并发同时执行的,所以三个任务之间是并发异步的

    2023-04-28归属地:湖北
  • peter
    请教老师两个问题: Q1:子线程之间可以用future和promise传递数据吗? Q2:结构化异常是什么意思?

    作者回复: Q1:子线程之间一般不会使用future和promise传递数据,你可以把A线程的future/promise给B使用也能进行数据通信,但一般来说会使用其他的线程间通信方案。 Q2:结构化异常是微软对C语言的异常处理扩展(C语言不支持异常),感兴趣可以自己看一下SEH(Structured Exception Handling)的相关内容。 链接(仅供参考):https://learn.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170

    2023-01-31归属地:北京
  • Geek_7c0961
    github 上面的星最多的线程池实现, 可以收藏. https://github.com/progschj/ThreadPool/blob/master/ThreadPool.h
    2023-02-07归属地:美国
    2
收起评论
显示
设置
留言
6
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部