首页 > 其他 > 详细

同步、异步、阻塞、非阻塞详解

时间:2016-02-22 19:02:25      阅读:305      评论:0      收藏:0      [点我收藏+]

为了阐释方便,需要先引入一个概念:

比进程小的可以是线程,比线程还小的是什么呢?--协程
协程:在线程中一个不带返回值的函数调用叫做协程。(我们暂且这样定义)
比如一个线程执行了以下流程:
     做饭-吃饭
那么做饭的过程就叫协程,吃饭的过程也叫协程。

同步、异步在阐述场景的时候总是容易和阻塞与非阻塞混淆,其实他们是不同维度的概念。
同步、异步: 描述的是协程之间的关系;
阻塞、非阻塞:描述的是一个协程的属性;

这里的"协程"不能换成"线程",因为单"线程"也可以通过某种办法维护很多并行的协程,比如IO复用。
这里的"协程"也不能换成"事件",因为"事件"不是用于描述过程的;
这里的"协程"也不能换成"函数",因为"函数"是代码中的概念;
这里的"协程"也不能换成"任务",因为"任务"有可能是一个流水线,甚至可能要多个线程完成。

阻塞:协程执行过程中会让线程挂起;

比如:A在焖米饭,没看焖好就一直等在电饭锅边,什么也不干;

非阻塞:协程在执行过程中没有完成也返回;

比如:A在焖米饭,看见没焖好米饭,也去干别的事了;
但是A需要隔一会就看一下米饭是否熟了。
所以在非阻塞的实现过程中,为了保证得到结果,有时需要设计轮询的方式来实现。
比如:《Unix环境网络编程》中,第六章说的recvfrom

同步:一件事完成之后才能做另一件事,与线程和进程数基本无关,因为它描述的是协程之间的关系。
比如:做好饭后才能吃饭。也可以细分成多种情况:
A做好饭后,A才能吃饭;(一般的函数都是这个范畴:如read/write)
A做好饭后,B才能吃饭;(锁、互斥量就是解决这个问题的)
A做好饭后,ABCDEF...才能吃饭;(条件变量就是解决这个问题的)

异步:与同步相反,做事并不依赖于其他事产生的结果。
比如:A做好饭了我就吃,没做好饭我也不会张着嘴在饭桌前干等着,该干什么干什么。
Linux中通常说的AIO,epoll(),libevent等都是异步的主要应用。

异步实现有两种方式:
(1)信号:A做好饭之后,敲个钟;
(2)回调函数:

综上,可以得到以下结论:

阻塞是实现同步的一种手段。(锁、互斥量、条件变量等的实现都是要让线程挂起)
轮询时保证非阻塞函数能够得到肯定结果的一种手段。(另外一种方式就是需要用异步的方式触发了)
异步可以是保证非阻塞函数得到肯定结果的一种手段。

如果看着有些糊涂,那么我们用Linux的IO来介绍一下阻塞、非阻塞、同步、异步这些概念:

基本的Linux IO矩阵

技术分享

同步阻塞:
如read/write,在结果返回之前,当前线程会被挂起,函数只有在得到结果之后才会返回。recvfrom举例如下:

技术分享

同步非阻塞:
如read/write的fd指定O_NONBLOCK,在不能立刻得到结果之前,函数不会阻塞当前线程,而会立刻返回。
当前线程也可以执行其他的操作,但得到的返回值是不一样的,如果返回值比较重要,就需要轮询,比如recvfrom函数
虽然不会阻塞进程,但需要不断轮询来查询结果:

技术分享
异步阻塞:
如IO复用中的select, 同时维护着多个文件描述符,只要有一个描述符返回时,返回值就大于0。
当然,select函数实现了单线程的异步,其实如果每个线程都维护一个任务,任务之前通过锁来保证执行顺序,这才是通常意义上的异步阻塞。recvfrom举例如下:

技术分享

异步非阻塞:
如AIO,linux中的epoll,先把函数注册给相应的事件,当满足条件之后,触发相应的操作。recvfrom举例如下:

技术分享

技术分享

本文参考以下大神博客:

http://blog.csdn.net/heyutao007/article/details/7065166
http://blog.chinaunix.net/uid-26000296-id-3754543.html
http://blog.chinaunix.net/uid-26000296-id-3754118.html

同步、异步、阻塞、非阻塞详解

原文:http://www.cnblogs.com/bugutian/p/5207909.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!