专栏首页开发 & 算法杂谈也谈应用程序级的同步、异步、阻塞、非阻塞

也谈应用程序级的同步、异步、阻塞、非阻塞

同步IO(synchronous)

异步IO(asynchronous)

阻塞IO(blocking)

非阻塞IO(non-blocking)

这几个经常出现的词汇很容易会引起大家的误解,第一次接触相关词汇是在课上,当时上操作系统的老师说得比较模糊(阻塞==同步,非阻塞==异步),当时觉得挺对 的,

初学者一般来说很会这么认为。但是后来随着对操作系统的进一步认识和学习,以及参考其他的一些资料,今天就在这帮大家理一理这四个概念以及相关的联系。

阻塞,在操作系统的书中都有相关的概念,简单的说 就是线程或是进程在执行过程中暂停,以等待某个条件的触发。

同步,指的就是两个或多个以上的进程保持相互的制约,一般多用在 通信当面的词。

接下来就说一上述困扰大家的四个词之间的相互关系:

同步阻塞IO:

应用场景:

应用程序A执行了一个read操作,然后这个read操作会去进行一个系统调用(system call),转交给内核,应用程序便会等待(阻塞),kernel便会开始执行系统调用,执行

完成之后将结果返回给应用程序,应用程序得到结果后就不在阻塞,继续后续的过程。

打个比方就是,你去医药窗口花钱买药 ,告诉药剂师要买一盒感冒药,药剂师就去帮你去里面的药架上找感冒药,你就站在窗口等,他找到后拿到窗口给你,其实就是一

个同步阻塞的过程。

同步非阻塞IO:

应用场景:

在linux下,应用程序可以通过设置文件描述符的属性O_NONBLOCK,I/O操作可以立即返回,但是并不保证I/O操作成功。也就是说,当应用程序设置了O_NONBLOCK之

后,执行write操作,调用相应的system call,这个system call会从内核中立即返回。但是在这个返回的时间点,数据可能还没有被真正的写入到指定的地方。也就是说,kern

el只是很快的返回了这个 system call(这样,应用程序不会被这个IO操作blocking),但是这个system call具体要执行的事情(写数据)可能并没有完成。而对于应用程序,

虽然这个IO操作很快就返回了,但是它并不知道这个IO操作是否真的成功了,如果想知道,需要应用程序主动地去问kernel。

打个比方就是,你去邮局寄东西(东西很重要,对方拿到后你才能够继续进行工作),填好 单子付完款后,邮局工作人员会告诉你,大概要三天到(邮局今天的囤货太多

了,改到明天发),然后你本人肯定就回去了,在家里等啊等,并且时不时的查查到哪了(不能继续进行下面的工作啊,诶 :( )。终于三天后收件人发信息说已经收到,你终

于可以开展你的下一步工作了 :)

异步阻塞IO:

应用场景:

在linux下,通常用select/poll来实现这种机制。应用程序要执行read操作,因此调用一个system call,这个system call被传递给了kernel。但在应用程序这边,它调用syst

em call之后,并不等待kernel返回响应,这一点是和前面两种机制不一样的地方。这也是为什么它被称为异步的原因。但是为什么称其为阻塞呢?这是因为虽然应用程序是一

个异步的方式,但是select()函数会将应用程序阻塞住,一直等到这个system call有结果返回了,再通知应用程序。也就是说,“在这种模型中,配置的是非阻塞 I/O,然后使用

阻塞 select 系统调用来确定一个 I/O 描述符何时有操作。”所以,从IO操作的实际效果来看,异步阻塞IO和第一种同步阻塞IO是一样的,应用程序都是一直等到IO操作成功之后

(数据已经被写入或者读取),才开始进行下面的工作。异步阻塞IO的好处在于一个select函数可以为多个描述符提供通知,提高了并发性。

打个比方就是,一个银行柜台,现在有10个人想存钱。按照现在银行的做法,一个个排队。第一个人先填存款单,然后提交,然后柜员处理,然后给回执,成功后再轮到

下一个人。大家应该都在银行排过对,这样的流程是很痛苦的。如果按照异步阻塞的机制,10个人都填好存款单,然后都提交给柜台,提交完之后所有的10个人就在银行大厅

等待。这时候会专门有个人,他会了解存款单处理的情况,一旦有存款单处理完毕,他会将回执交给相应的正在大厅等待的人,这个拿到回执的人就可以去干其他的事情了。

而前面提到的这个专人,就对应于select函数。

异步非阻塞IO:

应用场景:

应用程序提交read请求的system call,然后,kernel开始处理相应的IO操作,而同时,应用程序并不等kernel返回响应,就会开始执行其他的处理操作(应用程序没有被I

O操作所阻塞)。当kernel执行完毕,返回read的响应,就会产生一个信号或执行一个基于线程的回调函数来完成这次 I/O 处理过程。

打个比方就是,上述邮局寄东西,你寄完东西后不需要干等着,而可以干别的事情,等到收件人给你发收件信息后,你在回过头干之前没干完的工作。

总的来看的话,对于同步和异步,指的都是应用程序级的,而所谓的阻塞和非阻塞的话,指的是在内核调度进程或线程方面的。

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Redis基础数据结构小结

    最近在回顾Redis相关的一些基础知识,结合网上博客的一些分享,整理了一下思维导图,分享给有需要的同学~

    chain
  • PAT Basic 1002

    chain
  • Python多进程、多线程、协程

    在Unix/Linux中系统内核提供了fork系统调用来创建进程,根据不同的返回值来判断当前进程是子进程还是父进程,C语言代码示例如下:

    chain
  • 快速学习Oracle-pl/sql 基本语法

    PL/SQL(Procedure Language/SQL)PLSQL 是 Oracle 对 sql 语言的过程化扩展,指在 SQL 命令语言中增加了过程处理语...

    cwl_java
  • 你永远不想被问到的12个真实技术工作面试题

    大数据文摘
  • 老男孩Python全栈开发(92天全)视频教程 自学笔记20

    玩蛇的胖纸
  • 有图有真相

    自从上次简单讲解了飞思卡尔MQX RTOS系统后,不断有猿友留言,要求在讲讲启动流程,在一步步学习MQX系统的文章已经提到过,通过一步步跟踪可以清...

    用户1605515
  • C语言操作excel表格-链表实现

    https://blog.csdn.net/morixinguan/article/details/83309576

    morixinguan
  • 腾讯精选面试重点问题:Android源码分析--应用程序启动

    应用程序的启动,又可称为根Activity的启动。但是在讲应用程序启动之前,我们有必要对应用程序进程(AppProcess)启动有所了解,那是因为启动一个应用程...

    Android技术干货分享
  • NodeJS源码解析--Node如何处理HTTP请求

    看过我之前的写的文章的朋友们应该会知道,使用NodeJS创建一个HTTP服务器是非常简单的。我们写的一个个API中使用req来接收请求,使用re...

    逆月翎

扫码关注云+社区

领取腾讯云代金券