网站首页 > 技术文章 正文
一:阻塞与非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
1.blockingIO(阻塞):
1.1:阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返。有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。
1.2:对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。
socket接收数据函数recv是一个阻塞调用的例子。
1.3:当socket工作在阻塞模式的时候,如果没有数据的情况下调用该函数,则当前线程就会被 挂起,直到有数据为止。
图一就是recv函数在接受信息时的流程图
当用户进程调用了recv这个系统调用,内核就开始了IO的第一个阶段:准备数据。对于networkio来说,很多时候数据在一开始还没有到达,这个时候内核就要等待数据的到来。而在用户进程这边,整个进程会被阻塞。当内核一直等到数据准备好了,它就会将数据从网卡缓存区中拷贝到系统缓存区然后拷贝到用户指定缓存区中,然后内核返回结果,用户进程才解除阻塞状态,重新运行起来所以,blockingIO的特点就是在IO执行的两个阶段都被阻塞了。
2.nonblockingIO(非阻塞):
linux下,可以通过设置socket使其变为non-blocking。
2.1:非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
2.2:对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性,但是并不是一一对应的。
2.3;:阻塞对象上可以有非阻塞的调用方式,我们可以通过一定的API去轮询状态,在适当的时候调用阻塞函数,就可以避免阻塞而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。函数select就是这样的一个例子。
从图二是通过设置socket使其变为非阻塞。可以看出,当用户进程发出recv操作时,如果内核中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个error。从用户进程角度讲,它发起一个recv操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送recv操作。一旦内核中的数据准备好了,并且又再次收到了用户进程的recv调用那么它马上就将数据拷贝到了用户内存,然后返回。
所以,用户进程其实是需要不断的主动询问内核数据好了没有。
其实这样过程与阻塞本质是一样的只是需要不断的向内核询问,有数据到没有拷贝方式也和阻塞时一样。图三以select为例,我们每次将所有的文件描述符放入集合中通过select进行遍历进行查询如果有数据到来 集合就保留该文件描述符。这种方式的运行效率与用户的在线量成反比。
二、同步与异步
同步是两个对象之间的关系,而阻塞是一个对象的状态。
同步和异步关注的是消息通信机制(synchronouscommunication/ asynchronouscommunication)
所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。
换句话说,就是由*调用者*主动等待这个*调用*的结果。
而异步则是相反,*调用*在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。
1.synchronousIO(同步):
同步就是一旦调用那么就必须有结果才返回,在没有得到结果之前会一直等待,可能有些同学会问同步非阻塞呢,同步非阻塞是得到了结果的。只是这个结果表示没有数据或者error;
以上的阻塞和非阻塞均是同步状态。
2.asynchronousIO(异步):
如图五所示再用户进程发起recv操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受到一个asynchronousrecv之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,内核会给用户进程发送一个signal,告诉它recv操作完成了。
经过上面的介绍,会发现non-blockingIO和asynchronousIO的区别还是很明显的。在non-blockingIO中,虽然进程大部分时间都不会被阻塞,但是它仍然要求进程去主动的检查,并且当数据准备完成以后,也需要进程主动的再次调用recv来将数据拷贝到用户内存。而asynchronousIO则完全不同。它就像是用户进程将整个IO操作交给了他人(内核)完成,然后他人做完后发信号通知。在此期间,用户进程不需要去检查IO操作的状态,也不需要主动的去拷贝数据。
最后总结一下:
很多人也会把异步和非阻塞混淆,
因为异步操作一般都不会在真正的IO操作处被阻塞,
比如如果用select函数,当select返回可读时再去read一般都不会被阻塞
就好比当你的号码排到时一般都是在你之前已经没有人了,所以你再去柜台办理业务就不会被阻塞.
可见,同步/异步与阻塞/非阻塞是两组不同的概念,它们可以共存组合,
而很多人之所以把同步和阻塞混淆,我想也是因为没有区分这两个概念,
比如阻塞的read/write操作中,其实是把消息通知和处理消息结合在了一起,
在这里所关注的消息就是fd是否可读/写,而处理消息则是对fd读/写.
当我们将这个fd设置为非阻塞的时候,read/write操作就不会在等待消息通知这里阻塞,
如果fd不可读/写则操作立即返回.
注:需要C/C++ Linux服务器开发学习资料私信“资料”(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享
- 上一篇: 关于IO的同步,异步,阻塞,非阻塞
- 下一篇: 阻塞,非阻塞 ,同步,异步,并发,并行
猜你喜欢
- 2024-10-01 太详细了!Java语言异步非阻塞模式(原理篇)
- 2024-10-01 老张烧开水的故事-带你了解同步异步与阻塞非阻塞
- 2024-10-01 一文读懂并发与并行,同步与异步阻塞
- 2024-10-01 IO模型 阻塞 非阻塞 同步 异步概念对比区分
- 2024-10-01 精通Redis!epoll?IO的同/异步、阻塞/非阻塞?都懂了吗?
- 2024-10-01 深入理解非阻塞同步IO和非阻塞异步IO
- 2024-10-01 产品经理需要了解的那些技术2:同步、异步、阻塞、同步服务
- 2024-10-01 数据库讲坛|有关阻塞与非阻塞、同步与异步、I/O 模型-爱可生
- 2024-10-01 I/O模型 - 同步/异步/阻塞/非阻塞
- 2024-10-01 一个例子说清楚阻塞与非阻塞,同步与非同步
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)