阻塞 vs. 非阻塞 同步 vs. 异步

本文详细解析了socket通信中的关键概念:阻塞与非阻塞的区别,以及同步与异步的概念,并通过实例说明它们在实际应用中的表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

socket通信时,总是看到两对词汇不停的出现,但究竟他们各自分别代表什么内容,我就不甚了解了,甚至有的时候会把他们混淆起来叫,在查过UNP之后,有了一个比较粗浅的认识,在这里说一说.


通信,或者IO过程,总是分成了两个部分,第一个部分是检查数据是否准备就绪,第二个部分才是真正的IO操作,用户--OS缓冲区之间的数据移动,OS缓冲区--网络/磁盘等的一系列操作.

read操作可以这样理解:

1.读文件时,应该先检查文件数据是否就绪,比如被其他进程锁住,或者超出了文件的范围,那么此时文件的数据是没有就绪,无法读取的;如果没有上述情况,那么我们就开始真正的内容的复制

2.读管道时,首先是判断管道内有没有可读内容,如果没有的话,此时管道的数据就是没有就绪的,无法读取;如果没有上述情况,我们就可以进行真正IO操作获取管道内容

3.读网络通信时,首先是判断连接是否有效,该信息是否到达本机,如果信息不全,或者压根就没有,那么此时的网络数据就是没有就绪的,无法读取;否则,我们就可以通过IO操作获取内容

写时类似


也就是说,针对每个IO过程,我们都要看到两个阶段,一是数据的检验,二是数据的操作,而标题上两对词汇的不同之处,就在于这两个阶段的不同

阻塞和非阻塞是主要针对的是第一阶段,即数据的检验,二者在数据就绪的情况下没有区别,但是当数据没有就绪时,阻塞调用一般会等待数据就绪,从而"堵"住了进程,但非阻塞调用则会马上返回,通过返回值或者errno来反应目前的数据情况,常见的前者比如一般的read操作,后者则如设置了NONBLOCK的read操作.二者仅仅是第一阶段的不同,不管是哪个read,等到数据就绪真正读的时候,进程同样不能做其他任何事情,这就引出了我们的同步/异步

同步和异步主要针对第二阶段,也就是真正数据操作,如上所述,read和nonblock的read在数据就绪时,都会"堵"住进程,直到完成IO操作,在数据操作时,也就是真正的IO时"堵"住进程的,就叫做同步,否则,就叫做异步,比如aio调用,aio_read之后直接返回,数据操作完全有OS完成,之后通过信号/回调函数来通知进程操作完成.同步/异步不在于第一阶段表现如何,而是当进行真正IO操作时的表现,堵了就是同步,不堵就是异步.


由此回头来看Linux提供的一些高级的调用,select/poll/epoll基本都是针对第一阶段的调度,其价值不在于快速,而在于大规模的处理,就本质而言,调度成功后我们仍然通过同步操作来完成相关通信,不同之处在于,可能此时IO的两个阶段分的比较开,数据检验在调度中,有OS内部实现,数据操作(就绪的数据)被我们人为的推后了.而这种人为的推后,很多时候和异步很像,但仍然不是异步.


需要注意的是,此时同步/异步都是形容IO操作的,在现实中人们通常将分割开来的一系列操作成为异步,比如事件驱动的调度模型,就被很多人成为异步,此时的异步不是形容IO操作的异步,而是指请求和处理的分割,请求不是原地处理,而是进入请求队列,一般通过回调函数在合适的时候处理,从而形成异步效果.不要搞混这两个不同的概念.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值