异步执行和同步执行之间的区别是什么?


当前回答

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

同步或同步意味着“连接”,或在某种程度上“依赖”。换句话说,两个同步任务必须彼此知道,并且一个任务必须以依赖于另一个任务的某种方式执行,例如等待开始,直到另一个任务完成。 异步意味着它们是完全独立的,任何一方都不能以任何方式考虑另一方,无论是在初始化还是执行中。

同步(一个线程):

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和一个执行线程的机器,也可以在第一个任务完成之前开始第二个任务的处理。唯一的标准是,一个任务的结果不需要作为另一个任务的输入。只要任务的开始时间和结束时间重叠(只有在两个任务的输出都不需要作为另一个任务的输入时才有可能),它们就是异步执行的,不管使用了多少线程。

同步的例子:

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

其他回答

同步的不同英文定义在这里

协调;结合。

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

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

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

举个简单的例子,

同步

想象一下,三个学生被要求在公路上进行接力赛。

第一个学生跑完指定的距离,停下来把接力棒传给第二个。没有人开始跑步。

1------>
        2.
                3.

当第二个学生拿起接力棒时,她开始跑指定的距离。

      1.
        2------>
                3.

第二个学生解开了鞋带。现在她又停了下来,重新系上了领带。因此,2号的结束时间延长了,3号的开始时间推迟了。

      1.
        --2.--->
                3.

这种模式一直持续到第三名从第二名手中接过接力棒并完成比赛。

异步

想象一下,10个人随机走在同一条路上。 他们当然不是在排队,只是随机地在路上不同的地方以不同的速度行走。

第二个人的鞋带被解开了。她停下来又把它扎了起来。

但没人等着她把头发扎起来。其他人都还在以同样的速度走着他们以前的路。

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

以下是制作早餐的说明:

倒一杯咖啡。 烧热平底锅,然后煎两个鸡蛋。 煎三片培根。 烤两片面包。 在吐司上加黄油和果酱。 倒一杯橙汁。 如果你有烹饪经验,你会异步执行这些指令。你会先热锅煎鸡蛋,然后开始煎培根。你把面包放进烤面包机,然后开始煎鸡蛋。在这个过程的每一步,你都要开始一项任务,然后把注意力转移到那些已经准备好的任务上。 做早餐就是一个非并行的异步工作的好例子。一个人(或线程)可以处理所有这些任务。继续早餐的类比,一个人可以异步地做早餐,在第一个任务完成之前开始下一个任务。不管有没有人在看,烹饪都在进行。一旦你开始加热煎蛋的锅,你就可以开始煎培根了。培根烤好后,你可以把面包放进烤面包机。 对于并行算法,您需要多个cook(或线程)。一个做鸡蛋,一个做培根,等等。每个人都只专注于一项任务。每次烹饪(或线程)都将同步阻塞,等待培根准备翻转,或吐司爆裂。

(强调我的)

异步编程概念

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

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

同步与异步

同步和异步操作是关于下一个任务相对于当前任务的执行顺序。

让我们看一个例子,Task 2是当前任务,Task 3是下一个任务。Task是堆栈(方法帧)中的原子操作方法调用。

同步

意味着任务将逐个执行。当前任务完成后才会启动下一个任务。任务2完成后才启动任务3。

单线程+同步-顺序

通常执行。

伪代码:

main() {
    task1()
    task2()
    task3()
}

多线程+同步-并行

屏蔽。

阻塞意味着线程只是在等待(尽管它可以做一些有用的事情)。例如:Java ExecutorService[About] and Future[About])伪代码:

main() {
    task1()
    Future future = ExecutorService.submit(task2())
    future.get() //<- blocked operation
    task3()
}

异步

暗示任务立即返回控制,并承诺执行代码,稍后通知结果(例如。回调功能)。即使任务2没有完成,任务3也会执行。异步回调,完成处理程序

单线程+异步-并发

使用回调队列(消息队列)和事件循环(运行循环,循环器)。事件循环检查线程堆栈是否为空,如果为真,则将第一个项目从回调队列推入线程堆栈,并再次重复这些步骤。简单的例子是按钮点击,发布事件…

伪代码:

main() {
    task1()
    ThreadMain.handler.post(task2());
    task3()
}

多线程+异步-并发和并行

非阻塞。

例如,当你需要在不阻塞的情况下在另一个线程上进行一些计算。伪代码:

main() {
    task1()

    new Thread(task2()).start();
    //or
    Future future = ExecutorService.submit(task2())

    task3()
}

你可以使用阻塞方法get()或通过循环使用异步回调来使用Task 2的结果。

例如,在移动世界中,我们有UI/主线程,我们需要下载一些东西,我们有几个选择:

同步块-阻塞UI线程并等待下载完成。UI没有响应。 异步回调-创建一个新的线程,使用异步回调来更新UI(不可能从非UI线程访问UI)。回调地狱。 async coroutine[关于]-带有同步语法的异步任务。它允许将下载任务(挂起功能)与UI任务混合。

[iOS同步/异步],[Android同步/异步]

[并行vs并行]