0、前言
阻塞与非阻塞、同步与异步,这几个概念虽然每次看都能看的懂,但是过一段时间又会忘掉,所以系统的整理一下他们的区别,也方便自己后面忘掉的时候快速记忆,虽然网上有很多的说明这些概念的帖子,但是每次去找到能让自己明白的帖子也是一件不容易的事。
1、概念解释
1.1 阻塞与非阻塞
如果对于一次调用,比如说read(),如果是阻塞的话,当内核中数据没有准备好的情况下,该进程会阻塞当前的线程,进入休眠的状态,直到读取到数据。如果是非阻塞的话,会直接返回一个错误码。
1.2 同步与异步
同步指的是,我做一件事,总是要把它做完了以后再去做另一件事,即我调用一个函数,在没有得到结果之前,该调用不会返回。在用户线程发起 I/O 请求的时候,数据是有的,即将数据从内核缓存拷贝到用户空间的这个过程,用户线程是要等待着拷贝完成。
好,重点就是在这里,就是这个同步描述总是让人觉得它和阻塞不是一样的吗,但是实际上,阻塞的时候,当前的进程或者线程会休眠,会挂起,这个时候会让出CPU,但是同步不一样,同步是我一定要执行完我当前的任务,他是占有CPU的。
现在再看看什么是异步,异步就是,我发起了一个调用,我就去做另外一件事情了,在那件事情昨晚之后,通过回调函数等方式去通知我完成了这个任务。在用户线程发起 I/O 请求的时候,数据是有的,但是在数据从内核缓存拷贝到用户空间这个过程中,不需要用户线程等待,线程可以去执行其它逻辑,等内核将数据从内核空间拷贝到用户空间后,用户线程会得到一个通知。
那么再来看看异步与非阻塞的区别,看起来都是调用完直接返回了,但是异步会在事情完成之后告诉调用者,我完成了一个任务。
2、二者的区别
从大的角度来看,判断同步与异步的层次会高一些,它指的是数据还没有完成处理的时候,代码的处理的方式上的不同。同步和异步是指,内核的 I/O 拷贝实现,当数据准备就绪后,需要将内核空间的数据拷贝至用户空间,如果是同步 I/O 那么用户线程会等待拷贝的完成,而异步 I/O则这个拷贝过程用户线程该干嘛可以去干吗,当内核拷贝完毕之后会“通知”用户线程。
而阻塞与非阻塞指的是数据没有处理完的时候,线程的状态。阻塞和非阻塞指的是发起 I/O 请求后,用户线程状态的不同,阻塞I/O在数据未准备就绪的时候会 阻塞当前用户线程,而非阻塞 I/O 会立马返回一个错误,不会阻塞当前用户线程。