asynchronous与非阻塞
asynchronous调用和非阻塞调用有什么区别? 还有阻塞和同步调用(请举例)?
在许多情况下,它们对于同一事物是不同的名称,但在某些情况下,它们是完全不同的。 所以这取决于。 在整个软件行业中,术语不是以完全一致的方式应用的。
例如,在传统的套接字API中,一个非阻塞套接字是一个只是立即返回一个特殊的“would block”错误消息,而阻塞套接字将被阻塞的套接字。 你必须使用一个单独的函数,如select
或poll
来找出什么时候是重试的好时机。
但是asynchronous套接字(如Windows套接字所支持的)或.NET中使用的asynchronousIO模式更为方便。 你调用一个方法来启动一个操作,当这个框架完成时,框架会回复你。 即使在这里,也有基本的差异。 asynchronousWin32套接字通过传递Window消息将其结果“封送”到特定的GUI线程,而.NETasynchronousIO是自由线程的(不知道你的callback将被调用什么线程)。
所以他们并不总是意味着同样的事情。 为了提炼sockets示例,我们可以说:
- 阻塞和同步意味着同样的事情:你调用API,它挂起线程,直到它有某种答案,并返回给你。
- 非阻塞意味着如果答案不能很快返回,那么API会立即返回一个错误,而不会做其他事情。 因此,必须有一些相关的方法来查询API是否准备好被调用(即以一种有效的方式模拟一个等待,以避免手动轮询在一个紧密的循环中)。
- asynchronous意味着API总是立即返回,开始“背景”努力来满足您的请求,所以必须有一些相关的方式来获得结果。
- asynchronous是指并行执行的东西,也就是另一个线程。
- 非阻塞通常指轮询 ,即检查给定条件是否成立(套接字可读,设备具有更多数据等)
正如你可能从众多不同(而且往往是相互排斥的)答案中所看到的,这取决于你问的是谁。 在某些领域,术语是同义词。 或者他们每个人都可以提到两个相似的概念:
- 一种解释是,这个调用会在后台执行一些基本上无人监督的事情,以便让程序不被一个不需要控制的漫长过程所阻挡。 播放audio可能就是一个例子 – 一个程序可以调用一个函数来播放(比如说)一个mp3,从这个点开始可以继续到其他的东西,同时把它留给操作系统来pipe理在声音硬件上渲染audio的过程。
- 另一种解释是调用会做一些程序需要监控的事情,但是这个过程的大部分过程只能在后台进行,只能在程序的关键点通知程序。 例如,asynchronous文件IO可能就是一个例子 – 程序向操作系统提供一个缓冲区来写入文件,操作系统只在操作完成或发生错误时才通知程序。
无论是哪种情况,其目的都是让程序不被阻塞,等待一个缓慢的过程完成 – 程序如何应对是唯一真正的区别。 哪一个术语是指从程序员到程序员,语言到语言,或从平台到平台。 或者这些术语可能指的是完全不同的概念(如使用关于线程编程的同步/asynchronous)。
对不起,我不相信有一个正确的答案是全球性的。
把这个问题放到java 7的NIO和NIO.2中,asynchronousIO比非阻塞更先进一步。 使用Java NIO非阻塞调用,通过调用AbstractSelectableChannel.configureBlocking(false)
,可以设置所有通道(SocketChannel,ServerSocketChannel,FileChannel等AbstractSelectableChannel.configureBlocking(false)
。 然而,在这些IO调用返回之后,您可能仍然需要控制检查,例如是否以及何时再次读取/写入等。
例如,
while (!isDataEnough()) { socketchannel.read(inputBuffer); // do something else and then read again }
通过java 7中的asynchronousAPI,这些控件可以用更通用的方式制作。 2种方法之一是使用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) {...} } }
非阻塞调用立即返回任何可用的数据:请求的全部字节数,更less或根本没有。
asynchronous调用请求将在整个(整体)中执行的传输,但将在将来某个时间完成。
同步/asynchronous是描述两个模块之间的关系。
阻塞/非阻塞是描述一个模块的情况。
一个例子:
“我”:a
“书店”:b
a问b:你有一本名为“c ++ primer”的书吗?
1)阻断:在b应答之前,a一直在那里等待答案。 现在(一个模块)阻塞。 a和b是两个线程还是两个进程或一个线程还是一个进程? 我们不知道。
2)非阻塞:在b回答之前,a每隔两分钟就有一次来到这里寻找答案。 这里(一个模块)是非阻塞的。 a和b是两个线程还是两个进程或一个进程? 我们不知道。 但是我们确定a和b不能是一个线程。
3)同步:在b回答之前,a一直在等待答案。 这意味着,直到b完成工作,a才能继续。 现在我们说:a和b(两个模块)是同步的。 a和b是两个线程还是两个进程或一个线程还是一个进程? 我们不知道。
4)asynchronous:在答案a之前,a离开,一个可以做其他工作。 当b得到答案时,b会叫:嘿! 我拥有它! 那么当a免费的时候,一个会来b去拿这本书。 现在我们说:a和b(两个模块)是asynchronous的。 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);
你可以看到这个devise是非阻塞的(a是非阻塞的),而a和b是同步的,因为在从b获得消息之前,不能继续做任何事情。
通常在这种情况下,阻塞要好得多,因为非阻塞花费很多资源。 但是这个例子很好的帮助你理解这四个字:非阻塞并不意味着asynchronous。
非阻塞:这个函数不会在堆栈上等待。
asynchronous:在调用离开堆栈之后,可以继续工作以代表函数调用
他们只在拼写上有所不同。 他们提到的内容没有区别。 为了技术,你可以说他们的重点不同。 非阻塞是指控制stream(不会阻塞)。asynchronous是指处理事件\数据(不同步)。
阻塞:控制返回到原始(同步或asynchronous)处理完成后调用进动
非阻塞:控件在调用后立即返回到进程
阻止呼叫:仅当呼叫完成时,控制才会返回。
非阻塞呼叫:控制立即返回。 稍后操作系统以某种方式通知过程该通话已完成。
同步程序:使用阻止呼叫的程序。 为了在调用过程中不冻结,它必须有2个或更多的线程(这就是为什么叫同步 – 线程同步运行)。
asynchronous程序:使用非阻塞调用的程序。 它可以只有一个线程,仍然保持交互。