异步执行和同步执行有什么区别?
22 回答
当您同步执行某事时,您会等待它完成,然后再继续执行另一个任务。当您异步执行某事时,您可以在它完成之前继续执行另一个任务。
话虽如此,在计算机的上下文中,这转化为在另一个“线程”上执行进程或任务。线程是作为工作单元存在的一系列命令(代码块)。操作系统可以管理多个线程,并在切换到另一个线程以使其轮流做一些工作之前,为一个线程分配一块(“切片”)处理器时间。在其核心(请原谅双关语),处理器可以简单地执行命令,它没有同时做两件事的概念。操作系统通过将时间片分配给不同的线程来模拟这一点。
现在,如果您在混合中引入多个内核/处理器,那么事情实际上可以同时发生。操作系统可以将时间分配给第一个处理器上的一个线程,然后将相同的时间块分配给不同处理器上的另一个线程。所有这一切都是为了让操作系统管理您的任务的完成,同时您可以继续编写代码并做其他事情。
异步编程是一个复杂的话题,因为当你可以同时做它们时事物如何联系在一起的语义。有很多关于这个主题的文章和书籍;看一看!
同步/异步与多线程无关。
同步或同步意味着以某种方式“连接”或“依赖”。换句话说,两个同步任务必须相互了解,并且一个任务必须以某种依赖于另一个的方式执行,例如等待启动,直到另一个任务完成。
异步意味着它们是完全独立的,任何一方都不必以任何方式考虑对方,无论是在启动中还是在执行中。
同步(一个线程):
1 thread -> |<---A---->||<----B---------->||<------C----->|
同步(多线程):
thread A -> |<---A---->|
\
thread B ------------> ->|<----B---------->|
\
thread C ----------------------------------> ->|<------C----->|
异步(一个线程):
A-Start ------------------------------------------ A-End
| B-Start -----------------------------------------|--- B-End
| | C-Start ------------------- C-End | |
| | | | | |
V V V V V V
1 thread->|<-A-|<--B---|<-C-|-A-|-C-|--A--|-B-|--C-->|---A---->|--B-->|
异步(多线程):
thread A -> |<---A---->|
thread B -----> |<----B---------->|
thread C ---------> |<------C--------->|
<
用,>
字符表示的任务 A、B、C 的起点和终点。- 由竖线表示的 CPU 时间片
|
从技术上讲,同步/异步的概念实际上与线程没有任何关系。虽然,一般来说,在同一个线程上运行的异步任务是不常见的,但这是可能的(参见下面的示例),并且通常会发现两个或多个任务在不同的线程上同步执行......不,这个概念同步/异步的选择仅与第二个或后续任务是否可以在另一个(第一个)任务完成之前启动,或者它是否必须等待有关。就这些。什么线程(或多个线程),或进程,或 CPU,或者实际上,在什么硬件上执行任务是不相关的。事实上,为了说明这一点,我已经编辑了图形来显示这一点。
异步示例:
在解决许多工程问题时,该软件旨在将整个问题分解为多个单独的任务,然后异步执行它们。矩阵求逆或有限元分析问题就是很好的例子。在计算中,对列表进行排序就是一个例子。例如,快速排序例程将列表拆分为两个列表,并对每个列表执行快速排序,递归调用自身(快速排序)。在上述两个示例中,这两个任务可以(并且经常)异步执行。它们不需要位于单独的线程上。即使是一台只有一个 CPU 和一个执行线程的机器,也可以编码为在第一个任务完成之前启动第二个任务的处理。唯一的标准是一项任务的结果不需要作为另一项任务的输入. 只要任务的开始时间和结束时间重叠(仅当两者的输出都不需要作为另一个的输入时才可能),它们就会异步执行,无论有多少线程正在使用。
同步示例:
由多个任务组成的任何过程,其中任务必须按顺序执行,但必须在另一台机器上执行(获取和/或更新数据,从金融服务获取股票报价等)。如果它在单独的机器上,它在单独的线程上,无论是同步的还是异步的。
简单来说:
同步
你在排队买电影票。在你前面的每个人都得到一个之前,你不能得到一个,这同样适用于你后面排队的人。
异步
你和很多人在一家餐馆。你点你的食物。其他人也可以订购他们的食物,他们不必等到您的食物煮熟并送达您才可以订购。在厨房里,餐厅的工作人员不断地做饭、上菜和接单。人们将在食物煮熟后立即上菜。
同步执行意味着执行发生在一个系列中。 A->B->C->D
. 如果您正在调用这些例程,A
将运行,然后完成,然后B
将开始,然后完成,然后C
将开始,等等。
使用异步执行,您开始一个例程,并在您开始下一个例程时让它在后台运行,然后在某个时候说“等待这个完成”。它更像是:
开始 A->B->C->D->
等待A
完成_
优点是您可以在仍在运行时执行B
、C
和 or (在后台,在单独的线程上),因此您可以更好地利用资源并减少“挂起”或“等待”。D
A
同步意味着调用者等待响应或完成,asynchronous
调用者继续,响应稍后出现(如果适用)。
举个例子:
static void Main(string[] args)
{
Console.WriteLine("Before call");
doSomething();
Console.WriteLine("After call");
}
private static void doSomething()
{
Console.WriteLine("In call");
}
这将始终输出:
Before call
In call
After call
但是如果我们要制作doSomething
asynchronous
(有多种方法),那么输出可能会变成:
Before call
After call
In call
因为进行异步调用的方法将立即继续下一行代码。我说“可以”,因为异步操作无法保证执行顺序。它也可以按原样执行,具体取决于线程时间等。
同步与异步
Sync
和async
操作是关于执行顺序anext task
与current task
让我们看一个例子 where Task 2
iscurrent task
和Task 3
is a next task
。任务是原子操作 - 堆栈中的方法调用(方法框架)
同步- 意味着任务将被一一执行。Anext task
只有在current task
完成后才开始。Task 3
直到Task 2
完成才开始
单线程 + 同步 - 顺序通常执行。伪代码:
main() {
task1()
task2()
task3()
}
多线程 + 同步 - 并行- 阻塞。阻塞意味着一个线程正在等待(尽管它可以做一些有用的事情。例如 Java ExecutorService
[About]和Future
[About])伪代码:
main() {
task1()
Future future = ExecutorService.submit(task2())
future.get() //<- blocked operation
task3()
}
异步——意味着任务立即返回控制权并承诺执行代码并稍后通知结果(例如回调、功能)。Task 3
即使Task 2
没有完成也会执行。async callback
, completion handler
[关于]
单线程 + 异步 - 使用并发 Callback Queue
( Message Queue
) 和Event Loop
( Run Loop
, Looper
)。Event Loop
检查是否Thread Stack
为空,如果为真,则将第一个项目从其中推Callback Queue
入Thread Stack
并再次重复这些步骤。简单的例子是按钮点击,发布事件......伪代码:
main() {
task1()
ThreadMain.handler.post(task2());
task3()
}
多线程 + 异步 - 并发和并行非阻塞。例如,当您需要在另一个线程上进行一些计算而不阻塞时。伪代码:
main() {
task1()
new Thread(task2()).start();
//or
Future future = ExecutorService.submit(task2())
task3()
}
您可以使用阻塞方法get()
或async callback
通过使用任务 2 的结果loop
例如在移动世界中,我们有 UI/主线程,我们需要下载一些东西,我们有几个选择:
sync
block - 阻塞 UI 线程并在下载完成时等待。UI 没有响应。async
回调 - 创建一个带有异步回调的新线程以更新 UI(无法从非 UI 线程访问 UI)。回调地狱。async
coroutine [About] - 具有同步语法的异步任务。它允许将下载任务(挂起功能)与 UI 任务混合
我认为这是一个有点迂回的解释,但它仍然使用现实生活中的例子来澄清。
小例子:
假设播放音频涉及三个步骤:
- 从硬盘获取压缩歌曲
- 解压音频。
- 播放未压缩的音频。
如果您的音频播放器按顺序为每首歌曲执行步骤 1、2、3,则它是同步的。您将不得不等待一段时间才能听到这首歌,直到歌曲真正被提取并解压缩。
如果您的音频播放器执行步骤 1、2、3 彼此独立,则它是异步的。IE。在播放音频 1(步骤 3)时,如果它并行从硬盘获取音频 3(步骤 1)并并行解压缩音频 2。(第 2 步)您最终会听到这首歌,而无需等待太多提取和解压缩。
简单地说,异步执行就是在后台做事。
例如,如果您想从 Internet 下载文件,您可能会使用同步函数来执行此操作,但它会阻塞您的线程,直到文件完成下载。这会使您的应用程序对任何用户输入都没有响应。
相反,您可以使用异步方法在后台下载文件。在这种情况下,下载功能立即返回,程序继续正常执行。所有下载操作都在后台完成,完成后会通知您的程序。
作为一个非常简单的例子,
同步
想象一下 3 名学生被要求在公路上进行接力赛。
第一名学生跑了她给定的距离,停下并将接力棒传给第二名学生。没有其他人开始跑步。
1------>
2.
3.
当第二个学生取回接力棒时,她开始跑给定的距离。
1.
2------>
3.
第二个学生解开了她的鞋带。现在她又停下来绑起来了。因此,第二届的结束时间被延长,第三届的开始时间被推迟。
1.
--2.--->
3.
这种模式一直持续到第 3 名从第 2 名手中接过接力棒并完成比赛。
异步
想象一下 10 个随机的人走在同一条路上。他们当然不是在排队,只是在路上以不同的速度随意走在不同的地方。
第二个人的鞋带解开了。她停下来把它重新绑起来。
但是没有人在等她把它绑起来。其他人仍然以他们以前的方式行走,以同样的步伐。
10--> 9-->
8--> 7--> 6-->
5--> 4-->
1--> 2. 3-->
同步基本上意味着您一次只能执行一件事。异步意味着您可以一次执行多项操作,而无需完成当前操作即可继续执行下一项操作。
当执行类似 a>b>c>d> 的序列时,如果我们在执行过程中遇到失败,例如:
a
b
c
fail
然后我们从头开始:
a
b
c
d
这是同步的
但是,如果我们有相同的执行顺序:a>b>c>d>,而我们中间有一个失败:
a
b
c
fail
...但我们不是从头开始,而是从故障点重新开始:
c
d
...这被称为异步。
使用制作早餐的说明示例
- 倒一杯咖啡。
- 加热平底锅,然后煎两个鸡蛋。
- 煎三片培根。
- 烤两片面包。
- 在吐司中加入黄油和果酱。
- 倒入一杯橙汁。
如果你有烹饪经验,你会异步执行这些指令。你会开始为鸡蛋加热锅,然后开始培根。你把面包放在烤面包机里,然后开始鸡蛋。在流程的每一步,您都会开始一项任务,然后将注意力转移到准备好引起您注意的任务上。
做早餐是非并行异步工作的一个很好的例子。一个人(或线程)可以处理所有这些任务。继续早餐的类比,一个人可以通过在第一个任务完成之前开始下一个任务来异步制作早餐。无论是否有人在看,烹饪都会进行。一旦你开始为鸡蛋加热平底锅,你就可以开始煎培根了。培根开始后,您可以将面包放入烤面包机中。
对于并行算法,您需要多个厨师(或线程)。一个做鸡蛋,一个做培根,依此类推。每个人都只专注于那一项任务。每个厨师(或线程)将被同步阻塞,等待培根准备好翻转,或者吐司弹出。
您将同步与并行与串行混淆。同步意味着所有在同一时间。同步意味着彼此相关,可以意味着串联或固定间隔。虽然程序正在做所有事情,但它是串联运行的。拿一本字典……这就是我们喝不甜茶的原因。你有茶或加糖的茶。
同步操作在返回给调用者之前完成其工作。
异步操作在返回给调用者后完成(大部分或全部)其工作。
关于同步执行的“同时”定义(有时令人困惑),这是理解它的好方法:
同步执行:代码块中的所有任务都同时执行。
异步执行:代码块中的所有任务并非全部同时执行。
我认为一个很好的思考方式是经典的跑步接力赛
同步:进程就像同一个团队的成员,直到他们收到接力棒(前一个进程/运行器的执行结束)才会执行,但它们都彼此同步。
异步:在同一个接力赛道上的不同团队成员的进程类似,它们将运行和停止,彼此异步,但在同一个比赛中(整体程序执行)。
是否有意义?
同步的不同英文定义在这里
协调; 结合。
我认为这是比“同时发生”更好的定义。这也是一个定义,但我认为它不适合它在计算机科学中的使用方式。
因此,异步任务不与其他任务协调,而同步任务与其他任务协调,因此一个在另一个开始之前完成。
如何做到这一点是一个不同的问题。
同步意味着队列方式执行一个一个的任务将被执行。假设只有需要在朋友之间共享才能到达目的地的车辆将被共享。
在异步情况下,每个朋友都可以租到车辆并到达目的地。
是的,同步意味着同时,从字面上看,它意味着一起工作。世界上的多个人/物体可以同时做多件事,但是如果我们看一下计算机,它说同步意味着进程一起工作,这意味着进程依赖于彼此的返回,这就是它们被执行的原因一个接一个地以适当的顺序。而异步意味着进程不一起工作,它们可以同时工作(如果在多线程上),但独立工作。