并发是让两个任务在不同的线程上并行运行。但是,异步方法在同一个线程上并行运行。这是如何实现的?另外,并行性呢?
这三个概念有什么区别?
并发和并行实际上是您正确推测的相同原理,两者都与同时执行的任务有关,尽管我会说并行任务应该是真正的多任务,“同时”执行,而并发可能意味着任务共享执行线程,同时似乎仍在并行执行。
异步方法与前两个概念没有直接关系,异步用于呈现并发或并行任务的印象,但实际上异步方法调用通常用于需要在当前应用程序之外完成工作的进程,我们不这样做'不想等待并阻止我们的应用程序等待响应。
例如,从数据库中获取数据可能需要一些时间,但我们不想阻止我们的 UI 等待数据。异步调用采用回调引用,并在向远程系统发出请求后立即将执行返回给您的代码。您的 UI 可以在远程系统执行所需的任何处理时继续响应用户,一旦它将数据返回给您的回调方法,那么该方法可以适当地更新 UI(或移交该更新)。
从用户的角度来看,它看起来像多任务处理,但可能不是。
编辑
可能值得补充的是,在许多实现中,异步方法调用会导致线程启动,但这不是必需的,它实际上取决于正在执行的操作以及如何将响应通知回系统。
并发是指多个任务的执行是交错的,而不是每个任务一个接一个地顺序执行。
并行性是指这些任务实际上是并行执行的。
https://i.stack.imgur.com/V5sMZ.png
异步是一个单独的概念(即使在某些情况下相关)。它指的是一个事件可能在与另一事件不同的时间(不同步)发生。下图说明了同步和异步执行之间的区别,其中参与者可以对应不同的线程、进程甚至服务器。
https://i.stack.imgur.com/H5ysA.png
https://i.stack.imgur.com/GVMMy.png
有几种情况会发生并发:
异步——这意味着你的程序执行非阻塞操作。例如,它可以通过 HTTP 发起对远程资源的请求,然后在等待收到响应的同时继续执行其他任务。这有点像你发送一封电子邮件,然后继续你的生活而不等待回复。
并行性——这意味着您的程序利用多核机器的硬件通过将工作分解为任务来同时执行任务,每个任务都在一个单独的内核上执行。这有点像在淋浴时唱歌:你实际上是在同时做两件事。
多线程——这是一种允许同时执行不同线程的软件实现。即使在单核机器上运行,多线程程序似乎也在同时做几件事。这有点像通过各种 IM 窗口与不同的人聊天;尽管您实际上是在来回切换,但最终结果是您同时进行了多个对话。
每个人都很难将异步与并行或并发联系起来,因为异步不是并行或并发的反义词。它是同步的反义词。这只是表明某些东西(在这种情况下是线程)是否将与其他东西同步,在这种情况下是另一个线程。
并发意味着同时执行多个任务,但不一定同时执行。当您必须执行多个任务但您只有一个资源时,我们会选择并发。在单核环境中,并发是通过上下文切换来实现的。
并行性就像同时执行一项以上的任务,就像你可以一起唱歌和洗澡一样。现在您正在并行执行任务。
术语异步与线程执行有关。在异步模型中,当一个任务被执行时,您可以切换到另一个任务,而无需等待前一个任务完成。
异步编程帮助我们实现并发。多线程环境中的异步编程是实现并行性的一种方式。
“同步和异步是编程模型。并发和并行是执行任务的方式......”。来源:https://medium.com/better-programming/sync-vs-async-vs-concurrent-vs-parallel-5754cdb60f66
换句话说,sync 和 async 描述了您的程序在进行函数调用时如何执行(它会等待还是会继续执行?),而 concurrent 和 parallel 描述了函数(任务)将如何执行(并发 = 可能在同时,并行 = 同时有效执行)。
并发 并发意味着应用程序同时(同时)在多个任务上取得进展。好吧,如果计算机只有一个 CPU,则应用程序可能不会同时在多个任务上取得进展,但应用程序内部一次正在处理多个任务。在开始下一项任务之前,它并没有完全完成一项任务。并行性 并行性意味着应用程序将其任务分成更小的子任务,这些子任务可以并行处理,例如同时在多个 CPU 上。并发与并行的详细介绍 如您所见,并发与应用程序如何处理它所处理的多个任务有关。应用程序可以一次处理一个任务(顺序)或同时处理多个任务(并发)。另一方面,并行性与应用程序如何处理每个单独的任务有关。应用程序可以从头到尾顺序处理任务,或者将任务拆分为可以并行完成的子任务。如您所见,应用程序可以是并发的,但不是并行的。这意味着它同时处理多个任务,但这些任务不会分解为子任务。应用程序也可以是并行的,但不是并发的。这意味着应用程序一次只能处理一个任务,并且该任务被分解为可以并行处理的子任务。此外,应用程序既不能是并发的,也不能是并行的。这意味着它一次只能处理一个任务,并且该任务永远不会分解为并行执行的子任务。最后,应用程序也可以是并发和并行的,因为它既可以同时处理多个任务,也可以将每个任务分解为子任务以并行执行。但是,在这种情况下,并发性和并行性的一些好处可能会丢失,因为计算机中的 CPU 已经相当忙于并发性或并行性。结合它可能只会导致很小的性能提升甚至性能损失。确保在盲目采用并发并行模型之前进行分析和测量。
来自http://tutorials.jenkov.com/java-concurrency/concurrency-vs-parallelism.html
我将用简短而有趣的方式让您了解这些概念。
并发与并行 - 执行任务的方式。
举个现实生活中的例子:有一个挑战要求你既吃掉一个大蛋糕,又唱一首歌。如果您是唱完整首歌并完成蛋糕的最快的人,您将获胜。所以规则是你一边唱歌一边吃饭。你如何做到这一点不属于规则。你可以吃整个蛋糕,然后唱整首歌,或者你可以吃半个蛋糕,然后唱半首歌,然后再做一次,等等。并行是一种特定的并发,其中任务实际上是同时执行的。在计算机科学中,并行性只能在多核环境中实现。
同步与异步 - 编程模型。
同步地,您将代码编写为按顺序执行的步骤,从上到下。在异步编程模型中,您将代码编写为任务,然后并发执行。并发执行意味着所有任务很可能同时执行。
这里有一些语义需要澄清:
并发或并行是资源争用的问题,而异步是关于控制流的。
当它们的处理顺序没有确定性实现时,不同的过程(或它们的组成操作)被称为异步;换句话说,它们中的任何一个都有可能在任何给定时间T被处理。根据定义,多个处理器(例如CPU或Persons)可以同时处理其中的几个。在单个处理器上,它们的处理是交错的(例如线程)。
异步过程或操作在共享资源时称为并发;并发性是在任何给定时间 T 发生争用的明确可能性。当没有共享资源(例如不同的处理器和存储)时,并行性得到了微不足道的保证。否则必须解决并发控制问题。
因此,异步过程或操作可以与其他过程或操作并行或同时处理。
并行:这是一个广义的术语,意味着两段代码“同时”执行。它是“真正的”并行性还是通过一些巧妙的设计模式伪造的并不重要。关键是您可以同时启动“任务”,然后分别控制它们(使用互斥锁和所有适当的技巧)。但通常您更喜欢将“并行”一词仅用于“真正的”并行性,例如:您通过非协作多任务处理(无论是通过 CPU/GPU 内核,还是仅在软件级别通过让操作系统管理它来实现)处于非常低的水平)。人们不愿意仅仅为伪造并行性的复杂顺序代码说“并行”,例如您会在浏览器窗口的 javascript 中找到的那样。因此,该线程中的人们说“异步与并行性无关”的原因。确实如此,但不要混淆他们。
并发:没有并行性就不可能有并发(无论是模拟的还是真实的,正如我上面解释的那样),但是这个术语特别关注两个系统将在某个时间点同时尝试访问相同资源的事实。它强调你将不得不处理这个事实。
异步:每个人都说异步与并行无关,但它为它铺平了道路(让事情并行与否的责任在于你——继续阅读)。
“异步”是指并行性的一种表示形式,它形式化了通常涉及并行性的三个基本事物:1)定义任务的初始化(比如它何时开始以及它获得什么参数),2)完成后必须做的事情和 3)代码应该在两者之间继续做什么。
但它仍然只是语法(通常表示为回调方法)。在幕后,底层系统可能会简单地认为这些所谓的“任务”只是堆积起来的代码片段,直到它完成当前正在执行的代码。然后将它们一一解开并按顺序执行。或不。它还可能为每个任务创建一个线程并并行运行它们。谁在乎?该部分不包含在概念中;)
用类比来解释这些术语。
你的房子需要洗碗和洗衣服。
并发性:在开始另一个之前,您不会等待完成一个。例如,您可以先开始菜肴,也可以同时开始菜肴。他们可以按任何顺序完成,即即使您先开始洗碗,也可能先洗完衣服。
并行性:你家里有不止一个人在做这项工作;例如,您可以洗碗,而另一个人可以洗衣服。
异步:你告诉别人洗衣服,你告诉别人洗碗。他们实际上可以是同一个人(即您告诉他们洗衣服并立即告诉他们洗碗)。当他们完成每个任务时,他们会向您报告。
同步:你告诉别人洗碗。你等着他们。当他们完成后,您可以做其他事情(您可以告诉他们接下来洗衣服,或者您可以自己做,或者您可以完全做其他事情;关键是您在完成第一个任务时被阻止,您与他们同步)。
CONCURRENCY VS PARALLELISM:并发在一个时间点只能完成一项任务。示例:单 cpu 处理器在某一点上的并行性我们可以执行多个任务。例如:双核或多核处理器
我给出了现实世界的场景来解释 3 个主题假设你想去艾哈迈达巴德去孟买,但你不知道怎么走,所以你决定求助于地图应用程序(谷歌地图)。
非常正常但低效的方法是您可以在启动汽车之前观看完整路径,然后您开始驾驶并到达目的地。
并行 - 您可以不断地驾驶和观察路径。异步 - 你有你的朋友在车里,你给了他你的手机,打开了地图应用程序,告诉他看地图并指导你。并发 - 你开车几公里,把车停在一边,看地图,得到方向,然后重新开始开车等等。
总结
并发当多件事情似乎同时发生时(具有在并发任务之间快速切换的能力;它们是并发的,因为每个任务都需要一块资源、CPU 等)
当多个事情真正同时发生时并行(执行的线程数与执行的内核数密切相关)
异步简单地说是非阻塞的,当我们必须等待的事情不要让我们忙于等待时(需要某种通知机制才能从我们离开的点继续)
await asyncio.sleep
被认为是异步的并且是阻塞的。所以,异步并不意味着非阻塞。我认为异步没有真正的意义。此外,这里对并发和并行进行的区分似乎是武断的和捏造的。
async/await
通常是一种语言或(如在本例中)一个 library 构造。是什么让您认为它必须始终保持非阻塞?只是为了澄清 asynchronous
不等于 async/await
(请参阅那里的“等待”:))。 async/await
本质上也不是 fire-and-forget
,您在这里的理解似乎是什么。每当您必须等待结果时,它就会阻塞。但是,在 fire-and-forget
的情况下,您不必等待任何东西,因此直到最后都是非阻塞的。
当经理有几个工人并且可以给他们每个人一个单独的任务时,就会发生并行。工人们做他们的工作,并向经理提供结果。如果任务不能完全分离,例如对彼此的结果有一定的依赖关系,或者需要在没有其他推断的情况下专用相同的资源,则并行度受这些约束而无法完全实现。
当经理有多个任务但只有较少的工人时会发生并发,因此一些工人被赋予了多个任务。任何给定多个任务的工人,将每个原始给定任务分成几个步骤并交错执行步骤,每个任务结果将在每个步骤完成后立即返回给经理。经理收到任务结果,而其他任务开始并进行了几个步骤但尚未完成。如果任何具有多个任务的工作人员决定在完成已开始任务的每个步骤之前不开始给定任务的单个步骤,这称为顺序性。
从经理的角度来看,异步是上述两者中的任何一种混合或分离。当经理将任务分配给少数或足够的工人时,他不应等待,直到任何结果返回。他可以在工作进行时做他的个人工作或其他任何事情。通常工作人员不会决定如何将任务划分为步骤。控制反转意味着经理决定步骤并将单个步骤分配给工人。所以当他从一个工人那里收到一个步骤结果时,给他另一个步骤,也许是另一个任务。受控者也负责将后退步骤结果组合成任务结果。因此,异步性伴随着控制和协调的责任。如果要求任何工人按顺序工作,那么从经理的角度来看,他就是一个同步工人。
总结 很容易猜到,完全并行是一个无法实现的想法,除非在极少数情况下通常是微不足道的。由于现实伴随着相互依赖的任务和共享资源以及缺乏工人。所以并发是现实。从经理的角度来看,如果不妨碍他对任务的精细控制,这种并发是最好的,如果是肯定的,则称为异步。此外,在 SOLID 原则中由 S 增强的计算机软件工程最佳实践在历史上使服务器成为称为微服务的单步运行器,这将控制权返回给客户端。所以目前的情况是从服务器的角度来看是并发的,从客户端的角度来看是异步的。
Concurrent + Parallel 都意味着同时运行多个任务。我看到一些建议存在区别,但这取决于您咨询的参考资料,并且没有真正的正确或错误答案。
异步:在某些社区中,这意味着非阻塞代码,这可能意味着两件事:它几乎总是意味着它不会阻塞操作系统线程。但是,非阻塞可以选择意味着函数中的下一行源代码将继续运行而不会延迟。在 Python 中,await asyncio.sleep(5)
会阻止函数的执行,但不会阻止 OS 线程,这被认为是异步的。在 Golang 中,你有类似于 Python 的 await 的“goroutines”,它们阻止代码的执行,而不是 OS 线程,但是,这在 Golang 社区中不被称为异步。这只是并发编程。