有什么区别:异步,非阻塞,事件基础架构?

时间:2011-10-28 15:38:39

标签: programming-languages asynchronous blocking nonblocking event-based-programming

  1. 有什么区别:

    • 异步
    • 非阻止
    • 基于事件的架构?
  2. 某些内容可以是异步非阻止(以及基于事件的)吗?

  3. 编程中最重要的是什么:异步,非阻塞和/或事件基础(或所有3)?

  4. 如果您能提供示例,那就太棒了。

    这个问题正在被问到,因为我正在阅读这篇关于类似主题的精彩StackOverflow文章,但它没有回答我上面的问题。

5 个答案:

答案 0 :(得分:77)

<强>异步 异步字面意思是不同步。电子邮件是异步的您发送邮件,您不希望现在得到回复。但它不是非阻塞的。本质上它意味着一种架构,其中“组件”彼此发送消息而不期望立即响应。 HTTP请求是同步的。发送请求并获得回复。

<强>非阻断 该术语主要与IO一起使用。这意味着当你进行系统调用时,它会立即返回它所拥有的任何结果而不会使你的线程进入睡眠状态(很有可能)。例如,非阻塞读/写调用以他们可以做的任何方式返回,并期望调用者再次执行调用。 try_lock例如是非阻塞调用。只有在可以获取锁定时它才会锁定。系统调用的常用语义是阻塞的。 read将等到它有一些数据并将调用线程置于休眠状态。

<强>事件基 这个词来自libevent。非阻塞读/写调用本身是无用的,因为他们不会告诉你“何时”你应该回拨(重试)。 select / epoll / IOCompletionPort等是从“OS”中找出这些调用预期返回“有趣”数据的不同机制。 libevent和其他类似的库为各种操作系统提供的这些事件监视工具提供了包装器,并提供了一致的API来与跨操作系统的运行一起工作。非阻塞IO与Event-base密切相关。

我认为这些术语重叠。例如,HTTP协议是同步的,但使用非阻塞IO的HTTP实现可以是异步的。同样,像read / write / try_lock这样的非阻塞API调用是同步的(它会立即给出响应),但“数据处理”是异步的。

答案 1 :(得分:18)

在异步硬件中,代码要求某个实体做某事,并在动作完成时自由地做其他事情;一旦动作完成,实体通常会以某种方式发出代码信号。非阻塞体系结构将记录代码可能感兴趣的自发发生的操作,并允许代码询问这些操作发生了什么,但代码只有在明确询问这些操作时才会知道这些操作。当事件自发发生时,基于事件的体系结构将肯定地通知代码。

考虑一个串口,代码需要从该端口接收1,000个字节。

在阻塞读取架构中,代码将等待,直到1,000个字节到达或者它决定放弃。

在异步读取架构中,代码将告诉驱动程序它需要1,000个字节,并在1,000个字节到达时通知。

在非阻塞体系结构中,代码可能随时询问已到达多少字节,并且在其认为合适时可以读取任何或所有此类数据,但它知道所有数据何时到达的唯一方法是问;如果代码想要在第1000个字节到达的四分之一秒内找到它,它必须每隔四分之一秒检查一次。

在基于事件的体系结构中,串行端口驱动程序将在任何数据到达时通知应用程序。驱动程序不知道应用程序需要多少字节,因此应用程序必须能够处理小于或大于应用程序所需数量的通知。

答案 2 :(得分:3)

对我来说,非阻塞意味着线程中某个动作的执行不依赖于其他线程的执行,特别是它不需要批判部分。

异步意味着exectuion发生在调用者流之外,并且可能被隐藏。执行通常发生在另一个线程中。

读取并发数据是非阻塞的(无需锁定),但同步。反之,以同步方式同时写入数据是阻塞的(需要独占锁定)。从主流的角度来看,使其成为非阻塞的方法是使写入异步并推迟执行。

事件的概念是别的东西,粗略地说,这意味着当事情发生时你会得到通知。如果写入已异步执行,则可以引发事件,以便在执行写入后通知系统的其他部分。其他部分将回应此事件。系统可以仅根据事件构建,作为组件之间通信的唯一方式(考虑演员模型),但不一定非必要。

这三个术语是相关的,但对我来说是不同的概念。可能是人们以某种​​可互换的方式使用它们。

答案 3 :(得分:2)

通常,非阻塞体系结构基于方法调用,虽然它们可能会在 worker 线程上执行很长时间,但不会阻止调用线程。如果调用线程需要获取有关工作线程正在执行的任务的信息,则由调用线程来完成。

基于事件的体系结构基于响应于触发的事件而执行的代码的概念。代码执行的时间通常不是确定性的,但事件可能会调用阻塞方法;仅仅因为系统是基于事件的并不意味着它所做的一切都不会阻塞。

通常,异步架构是基于事件的非阻塞架构。

当进行异步调用时,事件处理程序向API注册,提供同步服务,以便通知调用者调用者感兴趣的内容已经发生。然后调用立即返回(非阻塞行为),调用者可以继续执行。当事件被激发回调用进程时,它们将在该进程中的某个线程上处理。

了解事件是否会在同一个线程上处理是很重要的,因为这会影响执行的非阻塞性,但我个人并不知道任何执行异步执行的库管理单个线程。

我删除了上一段,因为它并没有严格按照规定正确。我的意图是,即使系统中的操作是非阻塞的,例如调用OS工具并继续执行,单线程执行的本质意味着当事件发生时被解雇后,他们将在线程上与其他处理任务竞争计算时间。

答案 4 :(得分:1)

回答你的第一个和第二个问题:

非阻止实际上与异步相同 - 您拨打电话,稍后您会收到结果,但在发生这种情况时,您可以执行其他操作。阻止是相反的。在继续旅程之前,您等待回电。

现在异步/非阻塞代码听起来非常棒,而且确实如此。但我有警告的话。在受限制的环境中工作时,异步/非阻塞非常有用,例如在移动电话中...考虑有限的CPU /内存。它也适用于前端开发,您的代码需要以某种方式对UI小部件作出反应。

Async是所有操作系统需要工作的基础 - 它们会在后台为您完成任务并在您完成所要求的操作时唤醒代码,并且当该调用失败时,您就会#39 ;告诉它没有通过异常或某种返回代码/错误对象工作。

当您的代码要求需要一段时间才能响应的时候,您的操作系统知道它可能会忙于做其他事情。你的代码 -  进程,线程或等效块,块。您的代码完全忘记了操作系统在等待建立网络连接时,或者在等待来自HTTP请求的响应时,或者在等待读/写文件时,以及等等。你的代码可以简单地#34;等待鼠标点击。在此期间实际发生的事情是您的操作系统无缝管理,安排和响应事件&#34; - 操作系统正在寻找的东西,例如管理内存,I / O(键盘,鼠标,磁盘,互联网),其他任务,故障恢复等。

操作系统非常脆弱。硬核。他们非常擅长隐藏程序员的所有复杂的异步/非阻塞内容。这就是大多数程序员如何通过软件达到我们今天的目标。现在我们正在达到CPU限制,人们说可以并行完成工作以提高性能。这意味着异步/非阻塞似乎是一件非常有利的事情,是的,如果您的软件需要它,我可以同意。

如果您正在编写后端Web服务器,请谨慎操作。请记住,您可以水平缩放以便更便宜。 Netflix /亚马逊/谷歌/ Facebook是这条规则的明显例外,但纯粹是因为它使用更少的硬件对他们来说更便宜。

我会告诉你为什么异步/非阻塞代码是后端系统的噩梦....

1)它变成了对生产力的拒绝服务......你必须多思考,并且你在这个过程中犯了很多错误。

2)反应性代码中的堆栈跟踪变得难以理解 - 很难知道什么叫什么,何时,为什么以及如何。祝你好好调试。

3)你必须更多地思考事情是如何失败的,特别是当许多事情发生故障而不是你发送它们时。在旧世界,你一次做了一件事。

4)测试起来比较困难。

5)维护起来比较困难。

6)这很痛苦。编程应该是一种快乐和乐趣。只有像苦难一样的受虐狂。编写并发/反应框架的人是虐待狂。

是的,我已经写过同步和异步。我更喜欢同步,因为99.99的后端应用程序可以通过这种模式来实现。前端应用程序需要反应性代码,毫无疑问,这一直是他们的方式。

  1. 是的,代码可以是异步的,非阻塞的和基于事件的。

  2. 编程中最重要的是确保您的代码在可接受的时间内工作和响应。坚持这个关键原则,你就不会出错。

相关问题