深入理解--异步和非阻塞同步和阻塞异步和非阻塞

异步和非阻塞的概念实际上已经出现了很长一段时间。但是异步真正开始流行起来,是因为AJAX技术逐渐成为主流的web开发技术。非阻塞的概念真正流行起来,是当java引入NIO,也可以称作非阻塞IO的API,开始走进主流的开发人员的视线,真正流行起来,也可以认为是node.js带来的。

同步 ,异步,阻塞,非阻塞这几个概念相互之间联系紧密,很难区分。很多程序员都不知道它们之间的具体的不同。本文就会详细讨论这个问题,希望能帮助读者更好的了解这几个概念

同步和阻塞

首先,我们先开始介绍与异步和非阻塞对立的两个概念:同步和阻塞

对于web开发者来说,理解同步的概念相对比较容易,因为HTTP协议就是一个同步的协议。web浏览器向服务器发送一个请求并且等待它的响应。收到响应之后,浏览器才可以继续向服务器发送下一个请求,并且等待响应,周而复始的重复这个过程。在发送下一个请求之前必须等待响应的到达才行,这就成为了HTTP协议的一个巨大的性能瓶颈,当然为了解决这个问题,后来就出现了异步的AJAX技术。

阻塞的概念相对也是比较容易理解的。我们通过Java中的InputStream类的read方法来介绍阻塞的概念,文档中是这样描述read方法的:

If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown. 意思就是,如果已经到了流的末尾没有可读取的数据,那么就会返回-1。这个方法会一直阻塞,直到有可读取的数据,或者已经读到了流的末尾,或者抛出一个异常。

这个方法的调用会一直阻塞,因为他会一直等待直到输入的数据可以用来读取。这通常会造成性能的瓶颈,因为这个方法会阻塞,导致无法继续执行随后的操作。

异步和非阻塞

异步和非阻塞就是同步和阻塞的相反面。在直觉上,可能会感觉这两个概念会有一些类似,因为他们都可以允许你们的线程在等待结果或者返回的时候不需要挂起整个线程。但是他们又有不同,因为异步调用通常需要包括一个回调机制或者事件机制,去主动通知调用方此时响应的结果已经可用了。而非阻塞调用往往会先返回一个任意的结果,然后调用者会不定时的反复去尝试获取返回的结果,直到结果已经可用了。这里的区别就是一个主动通知和被动去询问。举个例子,你去音乐店买周杰伦的专辑,但老板告诉你,现在没货,你就回去了,等到货到了,准备好了,老板会主动打电话通知你,专辑已经到啦,快来买吧,这就是异步机制,是主动通知的。而非阻塞则是,老板不会主动通知你,而是你自己隔个一两天就去这家店主动问问,专辑到了么,直到有一次你询问的时候,终于发现专辑到了。非阻塞的概念常常用于I/O中,而异步的概念则相对应用的比较广泛。

特别的,异步I/O,意味着I/O操作是独立于当前的那个线程的操作而进行的。可以理解为,另外新开启了一个线程去执行I/O操作,当I/O操作完成之后会主动直接将结果返回。这里说的更详细一点就是,我们知道底层数据准备好之后,还要从内核区域拷贝到线程的缓冲区,非阻塞操作在这种意义上来说,又是同步的,因为非阻塞不会将这个拷贝数据的过程完成,而是当数据准备好了,告诉线程,你可以执行系统调用,将内核区域的数据拷贝到线程的缓冲区了,当然这个过程是同步,而且由于是系统调用,所以这个拷贝的过程也是阻塞的。而异步操作则不是,系统会开启一个线程当数据准备好了,这个线程还会完成这个从内核区将数据拷贝到线程缓冲区的过程,当数据拷贝完成了,才通知调用者,这时候调用者就直接可以用了。

我们在看一个更详细的异步I/O的例子:

我们假设同步I/O意味着发出一个I/O命令,然后一直等待,直到I/O操作完成。也就是说,你发出一个read命令,然后这个线程接下来的执行操作会一直等待,直到已经读到了内容。异步I/O则是你发出一个I/O命令,然后这个I/O不会立即完成。你可以先去执行接下来的程序。异步会实现一个接口,允许IO操作不阻塞当前的线程,而且当操作完成之后,会主动通知你操作已经完成。

Non-blocking 在这里有一个很好的解释: this StackOverflow answer:

This term is mostly used with IO. What this means is that when you make a system call, it will return immediately with whatever result it has without putting your thread to sleep (with high probability). For example non-blocking read/write calls return with whatever they can do and expect caller to execute the call again. try_lock for example is non-blocking call. It will lock only if lock can be acquired. Usual semantics for systems calls is blocking. read will wait until it has some data and put calling thread to sleep. 非阻塞I/O意味着当你发起一个系统调用的时候,他会立即返回一个结果,而不是将你的线程睡眠。非阻塞的读写操作,会收到一个立即的返回值,然后请求者会反复去重试,不断的去尝试,直到可以开始读写操作了。类似于忙等的状态,不断的测试,但是线程没有被阻塞。try_lock就是一个非阻塞的调用,他会尝试去获取锁,直到锁可以获取。通常来说,系统调用会进入内核,一般都是阻塞的,所以read操作往往是阻塞的,会等待可用数据,并且将线程休眠。

现在,我们应该对于异步和非阻塞的概念已经有所了解了。下面我们就举个现实中的例子来加强理解:

例如,传统的sockets API中,一个非阻塞的socket,通常会立即返回一个"would block" 的错误信息,然后需要调用独立的函数select or poll 去轮询检查什么时候可以再次尝试去读取。 但是异步的sockets (windows的sockets支持异步操作),.Net框架中也有异步I/O模型。你调用一个方法开始某个操作,然后 框架会在这个操作完成的时候,回调通知你,操作完成了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序你好

Zookeeper的功能以及工作原理

14110
来自专栏魏琼东

基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 会话

     会话从字面意义上来理解,是一次对话,在我们系统中怎么理解呢,会话就是一次交互,应和程序客户端和服务器端进行一个业务交互就是一个会话,会话生存与客户与服...

19860
来自专栏北京马哥教育

Linux 初步知识详解

1. 描述计算机的组成及其功能 一个完整的计算机系统由硬件系统和软件系统两大部分组成 冯诺依曼体系下的计算机五大部件 CPU:运算器、控制器、寄存器、缓存(一二...

42070
来自专栏我是攻城师

如何在Intellij IDEA中集成Gitlab

据说在微软收购github当天,一大批用户纷纷转向了gitlab和bitbucket,这两者也都是比较不错的代码托管网站,针对个人和企业都有对应的免费和收费版本...

16810
来自专栏数据和云

数据恢复-SQL被注入攻击程序的应对策略(ORA-16703)

前几天某客户紧急求助我们,其Oracle数据库由于重启之后无法正常启动。最后通过数据库全备进行了一天一夜的恢复,最后仍然无法正常打开数据库。 alter dat...

38760
来自专栏Java成神之路

Java微信开发_Exception_03_errcode:48001 errmsg:api unauthorized hint

异常信息:errcode:48001 errmsg:api unauthorized hint

15940
来自专栏cloudskyme

maven 学习总结

1、关于Maven 最近学了一些maven方面的知识,感觉这个工具挺好用,为防遗忘现总结一下。Maven是一个项目管理工具,它可以通过一段描述信息来管理项目的构...

35250
来自专栏跟着阿笨一起玩NET

WCF客户端和服务器时间不一致,导致通道建立失败的问题)

本文转载:http://www.cnblogs.com/bcbr/articles/2288374.html

24010
来自专栏aCloudDeveloper

Linux探秘之用户态与内核态

一、 Unix/Linux的体系架构 ?   如上图所示,从宏观上来看,Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核)。内核从本质上看是一...

25680
来自专栏散尽浮华

SVN和Git对比梳理

在日常运维工作中,经常会用到版本控制系统,目前用到最广泛的版本控制器就是SVN和Git,那么这两者之间有什么不同之处呢? SVN(Subversion)是集中式...

33860

扫码关注云+社区

领取腾讯云代金券