许多平台都将异步和并行性作为提高响应能力的手段。我通常了解这种差异,但经常发现我和其他人都难以阐明。
我是一个工作日的程序员,经常使用异步和回调。并行感让人感到异国情调。
但是我觉得它们很容易混淆,特别是在语言设计级别。很想清楚地描述它们之间的关系(或不存在关系),以及最适合应用它们的程序类别。
许多平台都将异步和并行性作为提高响应能力的手段。我通常了解这种差异,但经常发现我和其他人都难以阐明。
我是一个工作日的程序员,经常使用异步和回调。并行感让人感到异国情调。
但是我觉得它们很容易混淆,特别是在语言设计级别。很想清楚地描述它们之间的关系(或不存在关系),以及最适合应用它们的程序类别。
Answers:
当您异步运行某些内容时,这意味着它是非阻塞的,无需等待它完成并继续进行其他操作即可执行它。并行是指同时并行运行多个事物。当您可以将任务分解为独立的工作时,并行处理效果很好。
以3D动画的渲染帧为例。渲染动画需要很长时间,因此,如果要从动画编辑软件中启动该渲染,则应确保它是异步运行的,因此它不会锁定UI,并且您可以继续做其他事情。现在,该动画的每个帧也可以视为一个单独的任务。如果我们有多个CPU /核心或多个计算机,则可以并行渲染多个帧以加快整体工作量。
我相信主要区别在于并发和并行。
异步和回调通常是表达并发性的一种方式(工具或机制),即一组可能互相交谈并共享资源的实体。在异步或回调通信的情况下是隐式的,而资源共享是可选的(请考虑在远程计算机上计算结果的RMI)。正确地指出,这样做通常是考虑到响应能力。不要等待长时间的延迟事件。
并行编程通常以吞吐量为主要目标,而等待时间(即单个元素的完成时间)可能比等效的顺序程序更糟糕。
为了更好地理解并发和并行性之间的区别,我将引用Daniele Varacca的并发概率模型,该模型为并发理论提供了很好的注释:
当计算模型能够将系统表示为可能由相互独立的独立自主组件组成时,它就是并发模型。并发的概念不应与并行性的概念相混淆。并行计算通常涉及一个中央控制,该中央控制在多个处理器之间分配工作。同时,我们强调组件的独立性以及它们相互通信的事实。平行主义就像古埃及,法老王决定,奴隶在这里工作。并发就像现代的意大利一样,每个人都在做自己想做的事,所有人都使用手机。
总之,并行编程在某种程度上是并发的特殊情况,在这种情况下,单独的实体进行协作以获得高性能和吞吐量(通常)。
异步和回调只是允许程序员表达并发性的一种机制。考虑到众所周知的并行编程设计模式(例如master / worker或map / reduce)是由使用此类低级机制(异步)来实现更复杂的集中式交互的框架实现的。
本文对此进行了很好的解释:http : //urda.cc/blog/2010/10/04/asynchronous-versus-parallel-programming
它具有关于异步编程的功能:
异步调用用于防止应用程序内的“阻塞”。[Such a]调用将在一个已经存在的线程(例如I / O线程)中派生出来,并在可能的情况下执行其任务。
关于并行编程:
在并行编程中,您仍然要分拆工作或任务,但主要区别在于您为每个工作分块增加了新线程
总结:
异步调用将使用系统已经使用的线程,而并行编程则要求开发人员中断所需的工作,启动和拆卸线程。
我的基本理解是:
异步编程解决了在执行其他任何操作之前要等待昂贵的操作完成的问题。如果在等待操作完成时可以完成其他工作,那将是一件好事。示例:在运行时保持UI运行,并从Web服务中检索更多数据。
并行编程是相关的,但与将大型任务分解为可以同时计算的较小块有关。然后可以合并较小块的结果以产生总体结果。示例:光线跟踪,其中各个像素的颜色基本上是独立的。
它可能比这更复杂,但是我认为这是基本区别。
这是执行顺序的问题。
如果A与B异步,那么我无法预先预测A的子部分相对于B的子部分何时会发生。
如果A与B平行,则A中的事物与B中的事物同时发生。但是,执行顺序仍然可以定义。
也许困难在于异步这个词是模棱两可的。
当我告诉我的管家去商店买更多的葡萄酒和奶酪时,我执行了一个异步任务,然后忘了他,继续写我的小说,直到他再次敲开书房。并行在这里发生,但是我和男管家从事根本不同的任务,属于不同的社会阶层,因此我们在这里不使用该标签。
当每个女佣正在清洗不同的窗户时,我的女佣团队正在并行工作。
我的赛车支持团队是异步并行的,因为每个团队都在不同的轮胎上工作,他们在工作时不需要相互交流或管理共享资源。
我的足球(又名足球)团队进行并行工作,因为每个球员都独立处理有关该领域的信息并在其上移动,但是它们并不是完全异步的,因为他们必须交流并响应他人的交流。
当每个演奏者阅读音乐并控制他们的乐器时,我的游行乐队也是平行的,但是它们是高度同步的:他们彼此演奏并及时进行演奏。
凸轮式加特林机枪可以认为是平行的,但一切都是100%同步的,因此好像一个进程正在向前发展。
异步 假设您是客户的联系点,并且需要响应,即需要询问时共享状态,操作复杂性,所需资源等。现在您需要完成一项耗时的操作,因此由于需要响应客户端24/7,因此无法进行此操作。因此,您将耗时的操作委派给其他人,以便您能够及时响应。这是异步的。
并行编程 假设您有一个任务,要从一个文本文件读取100行,而读取一行则需要1秒钟。因此,您将需要100秒才能读取文本文件。现在,您担心客户端必须等待100秒才能完成操作。因此,您将再创建9个克隆,并使每个克隆从文本文件中读取10行。现在读取100条线仅需10秒。因此,您具有更好的性能。
综上所述,异步编码是为了实现响应性,并行编程是为了提高性能。
异步:在后台运行方法或任务,而不会阻塞。可能不必在单独的线程上运行。使用上下文切换/时间安排。
并行任务:每个任务并行运行。不使用上下文切换/时间安排。
我来这里的时候对这两个概念相当满意,但是我对它们并不清楚。
阅读一些答案后,我认为我有一个正确而有用的比喻来描述差异。
如果您将自己的代码行视为单独但有序的扑克牌(如果我在解释老式打孔卡的工作原理,请停止我的操作),那么对于每个单独编写的程序,您将拥有唯一的纸牌堆栈(不要复制和粘贴!),以及正常运行代码和异步运行代码正常运行之间的差异取决于您是否在乎。
运行代码时,您会向OS传递一组单个操作(您的编译器或解释器将您的“更高”级别的代码插入了这些操作)以传递给处理器。使用一个处理器,一次只能执行一行代码。因此,为了实现同时运行多个进程的错觉,OS使用了一种技术,即它一次只向给定进程发送几行处理器,并根据其看到的情况在所有进程之间进行切换适合。结果是多个过程似乎同时向最终用户显示进度。
对于我们的比喻,关系是操作系统总是在将卡发送到处理器之前先对其进行洗牌。如果您的纸牌叠不依赖于另一叠纸叠,则您不会注意到当另一叠纸叠处于活动状态时,您的纸叠不再被选中。因此,如果您不在乎,那就没关系。
但是,如果您确实在意(例如,确实存在相互依赖的多个进程-或成堆的卡-相互依赖),则操作系统的改组将使您的结果搞砸。
编写异步代码需要处理执行顺序之间的依赖性,而不管该顺序最终是什么。这就是为什么使用“回调”之类的构造的原因。他们对处理器说:“接下来要做的就是告诉另一个堆栈我们做了什么”。通过使用这样的工具,可以确保其他堆栈在允许操作系统运行其更多指令之前得到通知。(“如果Ifed_back == false:send(no_operation)”-不确定这实际上是如何实现的,但是从逻辑上讲,我认为它是一致的。)
对于并行流程,区别在于您有两个互不关心的堆栈,以及两个处理它们的工人。最终,您可能需要合并两个堆栈的结果,这将是一个同步问题,但是对于执行而言,您无需再担心。
不确定是否有帮助,但是我总是发现多种解释很有帮助。另外,请注意,异步执行不限于单个计算机及其处理器。一般而言,它处理时间,或者(甚至更一般而言)处理事件的顺序。因此,如果将相关的堆栈A发送到网络节点X,并将其耦合的堆栈B发送到Y,则正确的异步代码应该能够解决这种情况,就像它在笔记本电脑上本地运行一样。
以上所有答案的摘要
▪解决吞吐量问题。关于将大任务分解成较小的块
▪与机器有关(需要多台机器/内核/ CPU /处理器),例如:主从机,映射减少。
并行计算通常涉及一个中央控制,该中央控制可在多个处理器之间分配工作
▪解决了延迟问题,即在执行其他任何操作之前需要“等待”完成昂贵的操作的问题
▪与线程相关(需要多线程)
线程化(使用Thread,Runnable,Executor)是在Java中执行异步操作的一种基本方式