找回密码
 立即注册
搜索
查看: 408|回复: 0

通过分手厨房游戏深入理解协程 (coroutine) 的编程概念与应用

[复制链接]

9420

主题

0

回帖

2万

积分

管理员

积分
28470
发表于 2024-12-5 16:17:58 | 显示全部楼层 |阅读模式
介绍

如果你还在想了解什么是(),那么我们来玩一下 吧~

,是一款多人烹饪游戏,玩家需要在特定时间内烹饪尽可能多的菜肴。据说,一起玩耍的情侣会分手,所以又被称为“分手厨房”。你想挑战一下吗? (*^▽^*)

今天的主题是()。和分手厨房有什么关系? ()是现代编程中不可或缺的重要概念。它不仅让你的代码更加高级,也让你的程序在特定场景下表现得更好!

很多人花了很多时间不一定能理解它。然而游戏很容易理解,因此本文通过   游戏来谈谈什么是协程。

我们先来看看分手厨房怎么玩——

如上图所示,我们一共有四个玩家,每个玩家控制一个戴着厨师帽的反派(没有厨师帽的是一些NPC)。

游戏开始后,左上角会不断出现订单,玩家通过连续完成这些订单来得分。

每份订单都会注明需要什么材料,比如红色的是西红柿,灰色的是蘑菇等。每份订单都有自己的制作流程,比如先把西红柿切碎,然后煮熟,然后装盘上桌。哒哒,明白了这些规则就可以开始玩啦~

你做饭的速度越快,完成的订单越多,你的积分就越高。如何才能更快更好地完成订单?朋友之间需要分工明确,密切配合,不停地做饭。比如A同学负责切菜、拿食材,B同学负责做饭、上菜等,有时候有能力的人还要干更多的活。

规则简单,却需要大量的操作和配合。订单不断出现,长时间无法完成的订单将被销毁并扣除积分。煮了很久的食物如果不扑灭就会着火。如果着火了,你必须把火扑灭。两个人一不小心,没拿好该拿的食材,或者撞到一起就很容易发生冲突o(╥﹏╥)o

不过今天你不需要关心这些不简单的操作,你可以了解协程!

协程/

协程可以让计算机程序在IO密集型场景下支持更多的请求,节省更多的资源,并且比多线程有更好的性能。

那么什么是协程呢?维基百科的定义是——

协程是计算机程序的一个组件,它普及了允许暂停和恢复执行的协作多任务子例程。

定义中的关键词是协作、暂停和恢复。是不是有点难以理解?事实上,它们确实存在于分离厨房中:

· 协作,玩家不断协作下订单~

· 暂停。当食材切好入锅煮熟后,顺序就“暂停”了~

· 菜做好了就可以上菜了,订单恢复啦~

但与独立厨房相比,协程的美妙之处在于我们不必像游戏中的反派那样忙碌和不知所措。我们只需要声明要下的订单。电脑会在游戏中充当小人的角色,帮助我们漂亮地完成订单。这些命令是我们的代码,但与普通代码不同。它们是协程/在 async 和 wait 的帮助下构建的。它们看起来像同步代码,但计算机会异步执行它。

什么是同步代码,什么是异步方法?什么是异步执行和同步编写代码?

异步代码是什么?

首先,什么是同步和异步。什么是同步?

比如我们看视频的时候,如果画面和声音不同步,就会感觉很别扭。因此,同步可以理解为多个对象具有对应关系。

异步在我们的生活中很少用到。它通常出现在专业领域。比如异步IO,异步通信,英文。简单理解就是不同步。 (

类似于打散厨房,订单是以异步方式发出的——当订单出现时,当我们有空时,我们将获取食材并切蔬菜。但如果其他菜品准备好了,我们就会放下当前的订单,去处理其他订单。所以一开始就不点单,一直煮,直到点完单,然后再点其他的单。相反,其他订单的制定则穿插在中间。这是异步烹饪菜肴。



为了加深理解,我们再看一个例子——一周的工作

上课一周了

例如,我们有一个函数 AWeek。它要做的是打印星期一,播放音乐,打印星期二,刷新朋友圈,打印星期三。

同步代码如下所示:

<p><pre>    <code>function AWeek() {
  // 同步的代码,同步的方式
  print(&#39;Monday&#39;)
  play_music() // block call
  print(&#39;Tuesday&#39;)
  browse_moment() // block call
  print(&#39;Wednesday&#39;)
}</code></pre></p>
() 和 () 是阻塞调用。程序将等待这些事情完成,然后再继续下一步。

如果异步代码是非阻塞调用,它们会是什么样子?举个例子,在 async 和 await 出现之前的漫长日子里,它们是这样写的——

<p><pre>    <code>function AWeek() {
  print("Monday")
  Playing_Music(
    () => {
        print(&#39;Tuesday&#39;);
        ((cb) => {
            Browsing_Moment(cb);
        })(() => { print("Wednesday") });
    }
)
}</code></pre></p>
可以看到,代码以各种方式串在一起,很难理解,也很难维护(专家除外)。使用ES6,代码可以写成如下

<p><pre>    <code>function AWeek() {
  print("Monday")
  Playing_Music_Promise().then(() => {
    print(&#39;Tuesday&#39;);
    Browsing_Moment_Promise().then(() => {
        print(&#39;Wednesday&#39;);
    })
})
}</code></pre></p>
然后ES7有了async和await,代码就可以轻松写了

<p><pre>    <code>async function AWeek() {
  // 异步的代码,同步的方式编写
  print(&#39;Monday&#39;)
  await Playing_Music_Promise();
  print(&#39;Tuesday&#39;)
  await Browsing_Moment_Promise();
  print(&#39;Wednesday&#39;);
}</code></pre></p>
代码看起来和同步代码几乎一模一样,而且很容易理解和编写!不存在“一串一串”这样的东西。尽管它们看起来很相似,但它们确实是异步执行的,因为它们是协程。

执行的时候,如下图执行,中间加了很多框,做了很多事情。

因此,异步代码仍然按顺序做事,但它不是时间上连接的顺序,而是逻辑顺序。带有async、await、yield的函数是/,是异步代码。

重新谈判协议/

现在,在拆散厨房和工作一周(AWeek)之后,我们可以用更容易理解的方式来理解它——

协程/是函数,但它们是可以组合的函数,也就是说,你可以暂停这个函数的执行(直接返回到原来所在的位置),做其他事情,然后在适当的时候从上次中断的地方继续执行继续运行。 。

让我们插入线程看看它是如何实现的。下图左边灰色的那个(特殊功能)。当它被调用时,它被切割成两部分,蓝色框架和黄色框架:线程1执行完蓝色框架后,继续做其他事情;黄框的第二部分被遮挡。当机会出现时,线程 2(可以是线程 1)开始执行黄色框的第二部分。

在 C++20 中

使用 C++ 构建,C++20 添加了对协程/的支持。所以借助/,我们可以将我们强大的性能提升到一个新的水平,并且让编写和维护庞大的代码变得更加容易!

笔记

特别感谢我的同事 Roger 带我去玩  。

参考文档

%E5%8D%8F%E7%A8%8B
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|【科创星域】 ( 京ICP备20013102号-15 )

GMT+8, 2025-5-5 17:37 , Processed in 0.061423 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表