为什么要来写这篇文章呢?因为很多人会有类似的经历,分不清这两组概念的区别。

首先我要提几个问题:

1.阻塞/非阻塞和同步/异步 它们主语是谁呢?

2.为什么会有这两组概念呢?概念解释。

3.两组概念中,每组的我们实际应用中怎么选择呢?

 

第一个问题:(1.阻塞/非阻塞和同步/异步 它们主语是谁呢?)

无论是阻塞/非阻塞 、同步/异步,我们通常是指的对io的操作。

既然谈到io,那么io又是什么呢?

IO(input/output)是计算机输入和输出的接口,包括IO设备和IO接口。

说到IO设备我们不得不说,linux下面一切设备皆文件。那么对IO设备的操作就可以看做是对一个文件来操作。

对文件的读写操作,需要我们调用内核提供的系统命令,获取一个file descriptor(fd,文件描述符eg:对socket的读写也是需要系统调用获取文件描述符 socket fd),进而对文件描述符进行读写。

操作流程及用户态内核态各自的调用关系如下图:(此过程中进程的用户态和内核态 读者自行脑补)

 

 

阻塞:当我们调用read、recv等等系统调用API时,会把内核的缓存区里的数据拷贝到

用户态的缓存区里,如果这个时候内核缓存区里没有数据,则会等待内核把数据准备好,

此时,应用进程一直挂起状态。

 

非阻塞:当我们调用read、recv等等系统调用API时,会把内核的缓存区里的数据拷贝到

用户态的缓存区里,如果这个时候内核缓存区里没有数据,则会直接返回,明显用户态

程序没有任何等待。

 

第二个问题:(2.为什么会有这两组概念呢?概念解释。)

为什么会有这两种情况呢?

实际上是对现实情况的case覆盖,方便我们对每种case分情况处理。

 

阻塞/非阻塞

概念解释:

eg:socket的recv,我们接收数据的时候按照实际情况分类,

F1:如果没有数据我们一直等待着,不去做别的事情。(阻塞)

F2:每隔一段时间,我们都recv一下,如果没有数据,我们也返回去做别的事情。(非阻塞)

 

同步/异步

概念解释:

eg:一条tcp的连接

F1:读写都在同一个处理流程里(同步)

F2:读写在不同的处理流程中(异步)

 

第三个问题(3.两组概念中,每组的我们实际应用中怎么选择呢?)

首先要解释一下,阻塞/非阻塞和同步/异步没有必然的联系。

同步中可以有阻塞也可以有非阻塞,异步也是一样。

其实还是根据我们项目的实际情况来选择,一般情况来说异步io的读写是一种高效的方式(eg:aio)boost::asio。

同步的处理方式编写代码相对简单,如果业务场景对效率没有那么高的要求,而同步处理又能满足目前的业务场景,同步也是一种不错的选择。

而对于阻塞和非阻塞,这个简单一些,主要是看你业务场景自行脑补一下吧。

 

 

欢迎大家评论区各抒己见,技术在讨论中才有成长。

如果只是写写文章的话,可能没有说服里,贴上我github地址,在项目中体现上面情况。