异步执行与同步执行。有什么区别?

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

1067537 次浏览

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

例如,如果您想从Internet下载文件,您可以使用同步函数来执行此操作,但它会阻塞您的线程,直到文件完成下载。这可能会使您的应用程序对任何用户输入都没有响应。

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

当您同步执行某些内容时,您会等待它完成后再继续执行另一个任务。当您异步执行某些内容时,您可以在它完成之前继续执行另一个任务。

在操作系统的上下文中,这对应于在“线程”上执行进程或任务。线程是作为工作单元存在的一系列命令(代码块)。操作系统在处理器内核上运行给定的线程。然而,处理器内核一次只能执行单个线程。它没有同时运行多个线程的概念。操作系统可以通过将每个线程运行一小部分时间(例如1ms),并在线程之间持续切换,来提供同时运行多个线程的错觉。

现在,如果你在混合中引入多个处理器内核,那么线程可以同时执行。操作系统可以将时间分配给第一个处理器内核上的一个线程,然后将相同的时间块分配给不同处理器内核上的另一个线程。所有这些都是为了允许操作系统管理任务的完成,同时你可以继续编写代码和做其他事情。

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

同步执行表示执行发生在单个系列中。A->B->C->D。如果您调用这些例程,A将运行,然后完成,然后B将开始,然后完成,然后C将开始,等等。

使用异步执行,您开始一个例程,并在开始下一个例程时让它在后台运行,然后在某个时候说“等待此完成”。它更像:

开始A->B->C->D->等等A完成

这样做的好处是,您可以在A仍在运行时(在后台,在单独的线程上)执行BCD,因此您可以更好地利用资源,减少“挂起”或“等待”。

同步意味着调用者等待响应或完成,异步意味着调用者继续,响应稍后到来(如果适用)。

举个例子:

static void Main(string[] args){Console.WriteLine("Before call");doSomething();Console.WriteLine("After call");}
private static void doSomething(){Console.WriteLine("In call");}

这将始终输出:

Before callIn callAfter call

但是如果我们要使doSomething()异步(有多种方法),那么输出可以变成:

Before callAfter callIn call

因为进行异步调用的方法会立即继续下一行代码。我说“可以”,因为异步操作无法保证执行顺序。它也可以作为原始执行,取决于线程计时等。

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

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

同步(一个线程)

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      V1 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,则它是同步的。您将不得不等待一段时间才能听到歌曲,直到实际获取并解压缩歌曲。

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

当执行像a>b>c>d>这样的序列时,如果我们在执行过程中遇到失败,比如:

abcfail

然后我们从头开始:

abcd

这是同步的

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

abcfail

但我们不是从头开始,而是从失败的地方重新开始:

cd

…这被称为异步。

你混淆了同步和并行与系列。同步的意思是同时所有。同步的意思是与每个相关的,可以是串联的,也可以是固定间隔的。当程序做所有的事情时,它会串联运行。找一本字典…这就是为什么我们有不甜的茶。你有茶或加糖的茶。

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

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

简单来说:

同步

你在排队买电影票,只有排在你前面的每个人都拿到一张,你才能拿到一张,排在你后面的人也是如此。

异时

你和很多人在一家餐馆里,你点餐。其他人也可以点餐,他们不必等到你的菜煮熟了,端给你后才能点菜。在厨房餐厅,工人们不断地做饭、服务和接受订单。人们会得到他们的食物,因为它是煮熟的。

简单的类比解释

愤怒的员工

(故事和图片帮助你记住)。

同步执行

我的老板是个大忙人。他让我写代码。我告诉他:好的。我开始了,他像秃鹰一样看着我,站在我身后,从我肩膀上掉下来。我说:“伙计,WTF:你为什么不去做点什么,而我完成这个?”

他说:“不,我是0,直到你完成。”这是同步的。

异步执行

老板告诉我去做,而不是在那里等着我的工作,老板去做其他任务。当我完成工作时,我只是向老板报告说:“我完成了!”这就是异步执行。

(接受我的建议:永远不要和你背后的老板一起工作。

简而言之,同步是指两个或多个进程的开始结束点,不是它们的处决点。在这个例子中,进程A的端点与进程B的起点同步:

SYNCHRONOUS|--------A--------||--------B--------|

另一方面,异步进程没有的起点和终点是否同步:

ASYNCHRONOUS|--------A--------||--------B--------|

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

更新:Charles Bretana改进了他的回答,所以这个答案现在只是一个简单(可能过于简化)的助记符。

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

关于同步执行的“与此同时”定义(有时令人困惑),这里有一个很好的理解方法:

同步执行代码块中的所有任务都同时执行。

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

举个简单的例子,

同步

想象一下,3名学生被指示在公路上进行接力赛。

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

1------>2.3.

当第二个学生取回接力棒时,她开始跑她给定的距离。

      1.2------>3.

第二个学生解开了鞋带。现在她又停下来绑了起来。因此,第二个学生的结束时间延长了,第三个学生的开始时间也推迟了。

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

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

异时

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

第二个人的鞋带被解开了。她停下来再次把它绑起来。

但是没有人在等她把它绑起来。其他人仍然像以前一样走路,以他们同样的速度。

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

我认为一个很好的方式来考虑它是一个经典的运行接力赛

同步:进程就像同一个团队的成员,它们在收到接力棒(前一个进程/运行器的执行结束)之前不会执行,但它们都相互同步。

异步:进程类似于同一接力赛赛道上不同团队的成员,它们将运行和停止,彼此异步,但在同一比赛中(整体程序执行)。

有道理吗?

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

同步vs异步

同步和异步操作是关于执行命令到当前任务的下一个任务在关系

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

同步

意味着任务将一个接一个地执行。只有在当前任务完成后才会启动下一个任务。任务3在任务2完成后才会启动。

单线程+同步-顺序

普通处决。

伪代码:

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

多线程+同步-并行

封锁。

阻塞意味着线程正在等待(尽管它可以做一些有用的事情。例如JavaExecutorService关于我们Future关于我们)伪代码:

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

异步

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

单线程+异步-并发

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

伪代码:

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

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

非阻塞。

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

main() {task1()
new Thread(task2()).start();//orFuture future = ExecutorService.submit(task2())
task3()}

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

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

  • sync块-块UI线程并等待下载完成。UI没有响应。
  • async回调-创建一个带有异步回调的新消息来更新UI(无法从非UI线程访问UI)。回调地狱。
  • async协程关于我们-具有同步语法的异步任务。它允许将下载任务(挂起功能)与UI任务混合。

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

[并行vs并发]

同步的另一个英文定义是这里

协调;组合。

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

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

如何实现这一点是一个不同的问题。

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

我做了一个gif解释一下,希望对你有帮助:看,第3行是异步的,其他行是同步的。第3行之前的所有行应该等到第3行完成其工作之前,但由于第3行是异步的,下一行(第4行),不要等待第3行,但第5行应该等待第4行完成其工作,第6行应该等待第5行和第7行,因为第4,5,6,7行不是异步的。第3行是异步的,其他是同步的

做早餐的说明示例:

  1. 倒一杯咖啡。
  2. 加热平底锅,然后煎两个鸡蛋。
  3. 煎三片培根。
  4. 烤两片面包。
  5. 把黄油和果酱加到吐司里。
  6. 倒一杯橙汁。
  7. 如果你有烹饪经验,你会异步执行这些指令。你会开始加热锅里的鸡蛋,然后开始培根。你会把面包放进烤面包机,然后开始鸡蛋。在这个过程的每一步,你会开始一个任务,然后把你的注意力转移到准备好让你注意的任务上。

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

对于并行算法,你需要多个厨师(或线程)。一个人做鸡蛋,一个人做培根,依此类推。每个人只专注于一项任务。每个厨师(或线程)将被同步阻塞,等待培根准备好翻转,或者吐司流行。

(强调我的)

异步编程概念