异步与同步执行,它到底意味着什么?

Asynchronous vs synchronous execution, what does it really mean?

异步和同步执行有什么区别?


当您同步执行某个任务时,您将等待它完成,然后再继续执行另一个任务。当您异步执行某个任务时,您可以在它完成之前转到另一个任务。

也就是说,在计算机环境中,这意味着在另一个"线程"上执行一个进程或任务。线程是作为工作单元存在的一系列命令(代码块)。操作系统可以管理多个线程,并在切换到另一个线程之前为一个线程分配一段处理器时间("切片"),以便让它轮流执行一些工作。在其核心(请原谅双关语),处理器可以简单地执行一个命令,它没有同时执行两件事情的概念。操作系统通过将时间片分配给不同的线程来模拟这一点。

现在,如果您将多个核心/处理器引入到组合中,那么事情实际上可以同时发生。操作系统可以将时间分配给第一个处理器上的一个线程,然后将相同的时间块分配给另一个处理器上的另一个线程。所有这些都是关于允许操作系统管理任务的完成,而您可以继续编写代码并做其他事情。

异步编程是一个复杂的主题,因为它的语义是,当您可以同时进行时,事情是如何联系在一起的。关于这个问题有许多文章和书籍;请看一看!


同步/异步与多线程无关。

"同步"或"同步"在某种程度上表示"已连接"或"依赖"。换句话说,两个同步任务必须相互了解,并且一个任务必须以某种依赖于另一个任务的方式执行,例如等待启动,直到另一个任务完成。异步意味着它们是完全独立的,无论是在启动还是在执行中,任何人都不能以任何方式考虑另一个。

同步(一个线程):

1
1 thread ->   |<---A---->||<----B---------->||<------C----->|

同步(多线程):

1
2
3
4
5
thread A -> |<---A---->|  
                        \  
thread B ------------>   ->|<----B---------->|  
                                              \  
thread C ---------------------------------->   ->|<------C----->|

异步(一个线程):

1
2
3
4
5
6
         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-->|

异步(多线程):

1
2
3
 thread A ->     |<---A---->|
 thread B ----->     |<----B---------->|
 thread C --------->     |<------C--------->|
  • 任务A、B、C的起点和终点,用<>字符表示。
  • 用垂直条|表示的CPU时间片

从技术上讲,同步/异步的概念实际上与线程没有任何关系。虽然,通常情况下,在同一线程上运行异步任务是不常见的,但这是可能的(参见下面的示例),并且通常会发现两个或多个任务在不同的线程上同步执行…不,同步/异步的概念只与是否可以在另一(第一)个任务完成之前启动第二个或后续任务有关,或者是否必须等待。仅此而已。执行任务的线程(或线程)、进程或CPU,或者实际上是什么硬件,与此无关。实际上,为了说明这一点,我编辑了图形来显示这一点。

异步示例。在解决许多工程问题时,软件被设计成将整个问题分解为多个单独的任务,然后异步地执行它们。倒矩阵或有限元分析问题就是很好的例子。在计算中,排序列表就是一个例子。例如,快速排序例程将列表拆分为两个列表,并通过递归调用自身对每个列表进行排序。在上述两个例子中,这两个任务可以(并且经常)异步执行。它们不需要在单独的线程上。即使是一台有一个CPU,并且只有一个执行线程的机器,也可以在第一个任务完成之前进行编码,以启动第二个任务的处理。唯一的标准是一个任务的结果不需要作为另一个任务的输入。只要任务的开始和结束时间重叠(只有当两者的输出都不需要作为另一个的输入时才有可能),不管有多少线程在使用中,它们都是异步执行的。

同步示例。由多个任务组成的任何过程,其中任务必须按顺序执行,但一个任务必须在另一台机器上执行(获取和/或更新数据,从金融服务机构获取股票报价等)。如果它在一台单独的机器上,它在一个单独的线程上,不管是同步的还是异步的。


简单来说:

同步的

你排队买电影票。除非你前面的每个人都得到一个,否则你不能得到一个,同样的情况也适用于排在你后面的人。

异步的

你和许多其他人在一家餐馆里。你点的食物。其他人也可以点他们的食物,他们不必等到你的食物煮熟后再点。在厨房里,工作人员不断地做饭、上菜和点菜。人们一煮熟就会得到他们的食物。


类比的简单解释

同步执行

我的老板很忙。他让我写代码。我告诉他:好的。我开始了,他像秃鹰一样看着我,站在我身后,从我的肩膀上。我就像"哥们儿,wtf:你为什么不在我做完这件事的时候去做点什么?"

他说:"不,我在这儿等你做完。"这是同步的。

异步执行

老板叫我去做,而不是在那里等我的工作,而是老板离开去做其他的工作。当我完成工作后,我只需向我的老板汇报并说:"我完成了!"这是异步执行。

(接受我的建议:不要跟你后面的老板一起工作。)


同步执行是指在单个序列中执行。A->B->C->D。如果调用这些例程,A将运行,然后完成,然后B将启动,然后完成,然后C将启动,等等。

通过异步执行,您可以开始一个例程,并让它在后台运行,同时开始下一个例程,然后在某个时刻说"等待它完成"。它更像:

启动A->B->C->D->等待A完成

其优点是,当A仍在运行时(在后台,在一个单独的线程上),可以执行BC和或D,这样可以更好地利用资源,减少"挂起"或"等待"。


同步是指调用者等待响应或完成,异步是指调用者继续,然后响应(如果适用)。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
    static void Main(string[] args)
    {
        Console.WriteLine("Before call");
        doSomething();
        Console.WriteLine("After call");
    }

    private static void doSomething()
    {
        Console.WriteLine("In call");
    }

这将始终输出:

1
2
3
Before call
In call
After call

但是,如果我们要使剂量测量异步进行(有多种方法),那么输出可能会变成:

1
2
3
Before call
After call
In call

因为进行异步调用的方法将立即继续执行下一行代码。我说"可以",因为异步操作不能保证执行顺序。它还可以作为原始文件执行,这取决于线程计时等。


简而言之,同步是指两个或多个进程的起点和终点,而不是它们的执行。在本例中,流程A的端点与流程B的起点同步:

1
2
3
SYNCHRONOUS
   |--------A--------|
                     |--------B--------|

另一方面,异步进程的起点和终点不同步:

1
2
3
ASYNCHRONOUS
   |--------A--------|
         |--------B--------|

当进程A与进程B重叠时,它们会同时或同步运行(字典定义),因此会产生混淆。

更新:查尔斯布雷塔纳改进了他的答案,所以这个答案现在只是一个简单的(可能过于简单化)助记法。


我认为这是有点圆滑的解释,但它仍然澄清使用现实生活的例子。

小例子:

假设播放一个音频包含三个步骤:

  • 从硬盘获取压缩歌曲
  • 解压缩音频。
  • 播放未压缩的音频。
  • 如果音频播放器对每首歌曲按顺序执行步骤1、2、3,则它是同步的。你必须等待一段时间才能听到这首歌,直到它真正被提取出来并被解压缩。

    如果音频播放器的步骤1、2、3彼此独立,那么它是异步的。IE.在播放音频1(步骤3)时,如果它从硬盘并行获取音频3(步骤1),并并行解压缩音频2。(步骤2)你最终会听到这首歌,而不需要等待太多的获取和解压缩。


    简单地说,异步执行是在后台执行。

    例如,如果您想从Internet下载一个文件,您可以使用同步功能来完成此操作,但在文件下载完成之前,它会阻塞您的线程。这会使应用程序对任何用户输入都没有响应。

    相反,您可以使用异步方法在后台下载该文件。在这种情况下,下载函数立即返回,程序继续正常执行。所有下载操作都是在后台完成的,程序完成后会收到通知。


    同步编程模型——一个线程被分配给一个任务并开始处理它。一旦任务完成,它就可以用于下一个任务。在这个模型中,它不能让正在执行的任务处于中间位置来承担另一个任务。让我们讨论一下这个模型如何在单线程和多线程环境中工作。

    单线程——如果我们有几个任务要处理,而当前系统只提供一个线程,那么任务将逐个分配给线程。它可以用图形表示为
    Synchronous Single Threaded

    多线程——在这种环境中,我们以前有多个线程,它们可以承担这些任务并开始处理这些任务。这意味着我们有一个线程池(也可以根据需求和可用资源创建新的线程)和一堆任务。因此这些线程可以在这些线程上工作,如
    Synchronous Multi-Threaded

    异步编程模型——与同步编程模型相反,这里的线程一旦开始执行一个任务,就可以将其保持在中间,保存当前状态并开始执行另一个任务。

    单线程Asynchronous Single Threade

    多线程Asynchronous Multi-Threaded

    在这里阅读更多


    当执行类似:a>b>c>d>的序列时,如果执行过程中出现故障,如:

    1
    2
    3
    4
    a
    b
    c
    fail

    然后我们从头开始:

    1
    2
    3
    4
    a
    b
    c
    d

    这是同步的

    但是,如果我们有相同的执行顺序:a>b>c>d>,并且中间有一个失败:

    1
    2
    3
    4
    a
    b
    c
    fail

    …但是,我们不是从一开始就重新启动,而是从故障点重新启动:

    1
    2
    c
    d

    …这被称为异步。


    作为一个非常简单的例子,

    同步的

    想象一下,10个学生被指示在路上排队。

    第三个学生解开了鞋带。现在她停了下来,又系了起来。

    她后面的所有学生都停了下来,现在都在等她把它绑起来。第一和第二个学生已经走过他们所有人,并继续他们的正常步伐。

    1
    10-->9-->8-->7-->6-->5-->4-->3.     2-->1-->

    异步的

    想象10个随机的人走在同一条路上。当然,他们不是排队的,只是以不同的步调在路上的不同地方随意走动。

    第三个人的鞋带松了。她停下来把它再捆起来。

    但没人等她把它绑起来。其他人的步调仍然和以前一样。

    1
    2
    3
    4
    10-->    9-->
       8--> 7-->   6-->
     5-->  4-->  3. 2-->
    1-->


    您会混淆同步与并行vs系列。同步意味着同时发生。同步化是指相互关联,可以是串联的,也可以是固定间隔的。当程序执行所有操作时,它将连续运行。找本字典……这就是为什么我们要喝不加糖的茶。你有茶或甜茶。


    同步基本上意味着一次只能执行一件事情。异步意味着您可以一次执行多个任务,而不必完成当前任务就可以继续执行下一个任务。


    同步操作在返回调用者之前完成其工作。

    异步操作在返回到调用者之后(大部分或全部)完成其工作。


    我创建了一个GIF来解释这一点,希望能有所帮助:看,第3行是异步的,其他的是同步的。3号线之前的所有线路都应等到线路完成其工作之前,但由于3号线是异步的,所以下一条线路(4号线)不应等到3号线,但5号线应等到4号线完成其工作,6号线应等到5号线和7号线完成6号线,因为4、5、6、7号线不是异步的。line 3 is asynchronous and others are synchronous


    这里有一个不同的英语同步定义

    Coordinate; combine.

    我认为这是比"同时发生"更好的定义。这也是一个定义,但我不认为它符合计算机科学中使用它的方式。

    因此,异步任务不与其他任务协调,而同步任务与其他任务协调,因此一个任务在另一个任务开始之前完成。

    如何实现这一目标是另一个问题。


    请举例说明如何做早餐

  • 倒杯咖啡。
  • 把锅加热,然后煎两个鸡蛋。
  • 煎三片培根。
  • 烤两片面包。
  • 在吐司上加黄油和果酱。
  • 倒一杯橙汁。
  • 如果您有烹饪经验,您将异步执行这些指令。你先把平底锅烧鸡蛋,然后再烧培根。你把面包放在烤面包机里,然后开始煮鸡蛋。在这个过程的每一步,你都要开始一个任务,然后把注意力转向那些准备好让你注意的任务。

    烹饪早餐是异步工作的一个很好的例子。一个人(或线程)可以处理所有这些任务。继续进行早餐类比,一个人可以通过在第一个任务完成之前启动下一个任务来异步制作早餐。不管有没有人在看,烹饪都会进步。一旦你开始为鸡蛋加热锅,你就可以开始煎培根了。一旦培根开始,你可以把面包放进烤面包机。

    对于并行算法,您需要多个cook(或线程)。一个做鸡蛋,一个做培根,等等。每个人都将专注于这一项任务。每个厨师(或线程)将被同步阻塞,等待培根准备翻转,或烤面包弹出。

    异步编程概念参考


    对于同步执行的"同时"定义(有时会混淆),下面是理解它的一个好方法:

    同步执行:一个代码块内的所有任务都同时执行。

    异步执行:代码块内的所有任务并非都同时执行。


    我认为这是一场经典的跑步接力赛

    同步:进程和同一个团队的成员一样,在收到接力棒(上一个进程/运行程序的执行结束)之前不会执行,但它们都是同步的。

    异步:在同一中继竞赛轨道上,不同团队的成员等进程将运行和停止,彼此异步,但在同一竞赛(整个程序执行)内。

    这有道理吗?


    是的,同步意味着同时,字面意思是一起工作。世界上有多个人/对象可以同时做多件事,但如果我们看计算机,它说同步意味着进程一起工作,这意味着进程依赖于彼此的返回,这就是为什么它们以正确的顺序一个接一个地执行。而异步意味着进程不在一起工作,它们可以同时工作(如果在多线程上),但可以独立工作。


    同步意味着将逐个执行队列方式的任务。假设只有一辆车需要在朋友之间共享才能到达他们的目的地,一辆车一辆车将被共享。在异步情况下,每个朋友都可以租到汽车并到达目的地。