异步与非阻塞

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (10)
  • 关注 (0)
  • 查看 (100)

异步调用和非阻塞调用之间的区别是什么?还在阻塞和同步调用之间(请举例说明)?

提问于
用户回答回答于

在许多情况下,它们是同一事物的不同名称,但在某些情况下它们是完全不同的。所以这取决于。在整个软件行业中,术语的应用并不完全一致。

例如,在经典的套接字API中,一个非阻塞套接字是一个简单地以特殊的“would block”错误消息返回的套接字,而阻塞套接字会被阻塞。您必须使用一个单独的函数,例如select或poll,以发现什么时候是重试的好时机。

但是异步套接字(由Windows套接字支持),或使用的异步IO模式。净,更方便。您调用一个方法来启动一个操作,当它完成时,框架会调用您。即使在这里,也存在一些基本的差异。异步Win32套接字将其结果“编组”到特定的GUI线程上,通过传递窗口消息。NET异步IO是自由线程的(您不知道您的回调将被调用什么线程)。

所以它们并不总是相同的。为了提取套接字示例,我们可以这样说:

  • 阻塞和同步意味着同样的事情:调用API时,它会挂断线程,直到它有了某种答案并将其返回给您。
  • 非阻塞意味着如果不能快速返回一个答案,则API将立即返回错误,而不执行其他操作。因此,必须有一些相关的方法来查询API是否准备好被调用(也就是说,以一种有效的方式模拟等待,避免在紧循环中手动轮询)。
  • 异步意味着API总是会立即返回,已经启动了满足请求的“背景”工作,因此必须有一些相关的方法来获得结果。
用户回答回答于

阻塞:在处理原始(同步或异步)完成后,控制返回调用进程。

非阻塞:控制在调用后立即返回进程。

用户回答回答于

他们的拼写不同。他们所说的没有区别。说到技术,你可以说他们的重点不同。非阻塞是指控制流(它不阻塞)。异步指的是在处理事件\数据时(不同步)。

用户回答回答于

阻塞调用:只在调用完成时控制返回。

非阻塞调用:控制立即返回。稍后的操作系统以某种方式通知该调用已完成的过程。

同步程序:使用阻塞调用的程序。为了在调用期间不冻结,它必须有2个或更多的线程(这就是为什么它被称为同步线程的原因)。

异步程序:使用非阻塞调用的程序。它只能有一个线程,并且仍然保持交互。

用户回答回答于

非阻塞:此函数不会在堆栈上等待。

异步:在函数调用离开堆栈后,可以代表函数调用继续工作。

用户回答回答于

阻塞/非阻塞是描述一个模块的情况。

一个例子:

“我”:一个

“书店”:b

a问b:你有一本书叫“c++入门”吗?

1)阻塞:在b回答a之前,a一直在那里等待答案。现在,一个(一个模块)阻塞了。a和b是两个线程或两个进程或一个线程或一个进程?我们不知道。

2)非阻塞:在b回答a之前,a就在那里,每两分钟,a到这里来寻找答案。这里(一个模块)是非阻塞的。a和b是两个线程还是两个进程或一个进程?我们不知道。但是我们确定a和b不可能是一个线程。

3)同步:b回答a之前,a一直等待答案。这意味着a不能继续,直到b完成它的工作。现在我们说:a和b(两个模块)是同步的。a和b是两个线程或两个进程或一个线程或一个进程?我们不知道。

4)异步:在b回答a之前,a和a可以做其他的工作。当b得到答案时,b会叫a:嘿!我有它!当a有空的时候,a就会到b去取书。现在我们说:a和b(两个模块)是异步的。a和b是两个线程还是两个进程或一个进程?我们不知道。但是我们确定a和b不可能是一个线程。

这里有一个关于非阻塞和同步的典型例子:

// thread a
while (true)
{
    msg = recv(b, NON_BLOCKING_FLAG);
    if (msg is not empty)
    {
        break;
    }
    sleep(2000); // 2 sec
}

//thread b
// prepare the book for a
send(a, book);

您可以看到,这个设计是非阻塞的(a是非阻塞的),而a和b是同步的,因为a不能继续做任何事情,直到从b获得消息。

通常,在这种情况下,使阻塞更好,因为非阻塞花费了很多资源.。但是这个例子很好地帮助您理解这四个词:非阻塞并不意味着异步。

用户回答回答于

一个非阻塞调用立即返回任何可用的数据:请求的全部字节数,更少,或者根本没有。

异步调用请求将在其整个(全部)中执行的传输,但在将来的某个时间将完成。

用户回答回答于

在java 7中的NIO和NIO.2的上下文中,异步IO比非阻塞的要高级一步。对于java NIO非阻塞调用,可以通过调用以下方式将所有通道(SocketChannel、ServerSocketChannel、FileChannel等)设置为AbstractSelectableChannel.configureBlocking(false)但是,在那些IO调用返回之后,您可能仍然需要控制检查,比如是否和何时再次读/写,等等。

例如,

while (!isDataEnough()) {
    socketchannel.read(inputBuffer);
    // do something else and then read again
}

使用Java 7中的异步API,这些控件可以以更多的方式实现。两种方法之一是使用CompletionHandler.请注意,两者read调用是非阻塞的。

asyncsocket.read(inputBuffer, 60, TimeUnit.SECONDS /* 60 secs for timeout */, 
    new CompletionHandler<Integer, Object>() {
        public void completed(Integer result, Object attachment) {...}  
        public void failed(Throwable e, Object attachment) {...}
    }
}
用户回答回答于

正如您可能从众多不同的(而且往往是相互排斥的)答案中看到的,这取决于您询问的是谁。在某些领域,这些术语是同义的。或者,它们都可能引用两个类似的概念:

  • 一种解释是,呼叫将在后台做一些本质上没有监督的事情,以便使程序不被它不需要控制的冗长过程所阻碍。播放音频可能是一个例子-一个程序可以调用一个函数来播放(比如说)一个mp3,从那时起,它可以继续到其他事情上,同时让操作系统来管理在声音硬件上呈现音频的过程。
  • 另一种解释是,调用将做一些程序需要监视的事情,但允许大多数过程发生在后台,只在进程的关键时刻通知程序。例如,异步文件IO可能是一个例子--程序向操作系统提供一个缓冲区以写入文件,而操作系统只在操作完成或发生错误时通知程序。

在任何一种情况下,目的都是让程序不被阻塞,等待一个缓慢的过程完成--程序的响应方式是唯一真正的区别。哪个术语也是从程序员到程序员,语言到语言,或者平台到平台的变化。或者这些术语可能指完全不同的概念(例如,与线程编程相关的同步/异步的使用)。

用户回答回答于
  • 异步指已做的事并行说是另一条线。
  • 非阻塞常指轮询,即检查给定条件是否有效(套接字是可读的,设备有更多的数据,等等)。

扫码关注云+社区

领取腾讯云代金券