单线程与异步混淆
Single thread and asynchronous confusion
看了各种文章和类似的问题,知道这两个概念不一样,但是好像不知道正确答案。
我了解到thread
是工人数量,sync/async
是任务顺序。
请问我的理解是否正确,举个例子
要做三明治。
- 烤面包。
- 煎鸡蛋。
- 合并。
一根线==一个煎锅。
- 单线程&同步:
- 将面包放在煎锅上。
- 看着面包都烤好了。
- 面包烤好后,将面包从烤盘中取出,将鸡蛋放在烤盘上。
- 多线程和异步:
- 多个平底锅。
- 把面包和鸡蛋分别放在不同的盘子里。
- 不管你先放什么,把完成的拿出来。
- 单线程和异步:
- 一锅。
- 把面包放在烤盘上。
- 面包还没烤好,搁一会,把鸡蛋放在那个盘子上。
- 鸡蛋没有全炸,我就收起来,把面包放在锅里。
- 重复...
- 多线程和同步:
- 有几个平底锅,但我们先在平底锅1上烤面包。
- 当pan1上的面包做好后,在pan2上煎鸡蛋。
我的理解正确吗?
+) 如果是这样,单线程/异步如javascript,事件循环中的任务只是在队列中等待而不进行,对吗?
这个例子很好很有趣。不要忘记稍后将另一个用于“Multi-thread & async”,否则它会被烧毁;)。否则,在我看来总体上是正确的。
这个例子对于“Single-thread & async”的情况不是很好,它可能是混淆的根源。实际上,pre-emption(鸡蛋和面包之间的切换)在异步中不能保证。一般都是合作完成的。问题是在你的例子中,面包不能煮熟,而鸡蛋是因为只有 1 个平底锅。实际上,像 I/Os 操作这样的任务可以在不使用任何核心(即 pan)的情况下进行。
Async 主要用于避免等待任务完成而其他事情可以完成。它对计算任务并不是很有用。例如,如果你为 2 个朋友做了 2 个三明治,而你不知道他们喜欢鸡蛋还是灯塔,你需要问他们。这个任务可以是异步的:你可以问第一个,然后是第二个,然后用 1 或 2 个平底锅煮面包,然后在煮 eggs/beacon 之前检查答案。没有异步,你必须在烤面包之前等待答案(可能在线程中)(效率不高)。
异步操作可以拆分成多个部分:
- 开始请求(例如,向朋友发送消息)
- 检查状态或触发事件(例如,检查您的好友消息或在收到消息时做出反应)
- 完成请求(例如,开始准备您朋友想要的东西),其中可能包括开始新请求(在 1 中完成。)
第 2 部分依赖于 language/framework。而且,对于language/framework,有时会有一部分是等待任务完成(阻塞操作)。可以通过循环第 2 部分直到状态完成来完成,但有时可以更有效地完成。
看了各种文章和类似的问题,知道这两个概念不一样,但是好像不知道正确答案。
我了解到thread
是工人数量,sync/async
是任务顺序。
请问我的理解是否正确,举个例子
要做三明治。
- 烤面包。
- 煎鸡蛋。
- 合并。
一根线==一个煎锅。
- 单线程&同步:
- 将面包放在煎锅上。
- 看着面包都烤好了。
- 面包烤好后,将面包从烤盘中取出,将鸡蛋放在烤盘上。
- 多线程和异步:
- 多个平底锅。
- 把面包和鸡蛋分别放在不同的盘子里。
- 不管你先放什么,把完成的拿出来。
- 单线程和异步:
- 一锅。
- 把面包放在烤盘上。
- 面包还没烤好,搁一会,把鸡蛋放在那个盘子上。
- 鸡蛋没有全炸,我就收起来,把面包放在锅里。
- 重复...
- 多线程和同步:
- 有几个平底锅,但我们先在平底锅1上烤面包。
- 当pan1上的面包做好后,在pan2上煎鸡蛋。
我的理解正确吗?
+) 如果是这样,单线程/异步如javascript,事件循环中的任务只是在队列中等待而不进行,对吗?
这个例子很好很有趣。不要忘记稍后将另一个用于“Multi-thread & async”,否则它会被烧毁;)。否则,在我看来总体上是正确的。
这个例子对于“Single-thread & async”的情况不是很好,它可能是混淆的根源。实际上,pre-emption(鸡蛋和面包之间的切换)在异步中不能保证。一般都是合作完成的。问题是在你的例子中,面包不能煮熟,而鸡蛋是因为只有 1 个平底锅。实际上,像 I/Os 操作这样的任务可以在不使用任何核心(即 pan)的情况下进行。
Async 主要用于避免等待任务完成而其他事情可以完成。它对计算任务并不是很有用。例如,如果你为 2 个朋友做了 2 个三明治,而你不知道他们喜欢鸡蛋还是灯塔,你需要问他们。这个任务可以是异步的:你可以问第一个,然后是第二个,然后用 1 或 2 个平底锅煮面包,然后在煮 eggs/beacon 之前检查答案。没有异步,你必须在烤面包之前等待答案(可能在线程中)(效率不高)。
异步操作可以拆分成多个部分:
- 开始请求(例如,向朋友发送消息)
- 检查状态或触发事件(例如,检查您的好友消息或在收到消息时做出反应)
- 完成请求(例如,开始准备您朋友想要的东西),其中可能包括开始新请求(在 1 中完成。)
第 2 部分依赖于 language/framework。而且,对于language/framework,有时会有一部分是等待任务完成(阻塞操作)。可以通过循环第 2 部分直到状态完成来完成,但有时可以更有效地完成。