一文读懂,通俗讲解同步、异步、阻塞、非阻塞
1 五种IO模型
Unix网络编程一书中作者给出了五种IO模型:
1、BlockingIO - 阻塞IO
2、NoneBlockingIO - 非阻塞IO
3、IO multiplexing - IO多路复用
4、signal driven IO - 信号驱动IO
5、asynchronous IO - 异步IO
同步:自己的事自己做。去银行取了100块,自己去买了包烟。 异步:委托他人办事。如目标就是去银行取100块,取完后要做得事情是买1包香烟,剩余的当小费,香烟拿回家,晚上要用。假如一人为一线程,则需要两线程。 阻塞:等待结果(等待空闲资源)。假设去银行办事,设在窗口等待为阻塞,拿号在椅子等被叫号也是阻塞。 非阻塞:不等待结果。派张三去银行办事,发现没有空闲窗口立即走人,过了一段时间派李四去银行办事,重复以上。或者是银行规定,一天只接待一个客户,之后的都叫他们第二天再来试试。
2 阻塞与非阻塞 同步与异步
2.1 故事1
阻塞非阻塞与同步异步的区别?(故事篇) 理解同步阻塞、同步非阻塞、异步阻塞、异步阻塞、异步非阻塞
同步/异步关注的是消息通知的机制,而阻塞/非阻塞关注的是程序(线程)等待消息通知时的状态。
以小明下载文件打个比方,从这两个关注点来再次说明这两组概念,希望能够更好的促进大家的理解。
同步阻塞:小明一直盯着下载进度条,到 100% 的时候就完成。 - 同步体现在:等待下载完成通知。 - 阻塞体现在:等待下载完成通知过程中,不能做其他任务处理。
同步非阻塞:小明提交下载任务后就去干别的,每过一段时间就去瞄一眼进度条,看到 100% 就完成。 - 同步体现在:等待下载完成通知。 - 非阻塞体现在:等待下载完成通知过程中,去干别的任务了,只是时不时会瞄一眼进度条。【小明必须要在两个任务间切换,关注下载进度】
异步阻塞:小明换了个有下载完成通知功能的软件,下载完成就“叮”一声。不过小明不做别的事,仍然一直等待“叮”的声音。 - 异步体现在:下载完成“叮”一声通知。 - 阻塞体现在:等待下载完成“叮”一声通知过程中,不能做其他任务处理。
异步非阻塞:仍然是那个会“叮”一声的下载软件,小明提交下载任务后就去干别的,听到“叮”的一声就知道完成了。 - 异步体现在:下载完成“叮”一声通知。 - 非阻塞体现在:等待下载完成“叮”一声通知过程中,去干别的任务了,只需要接收“叮”声通知即可。【软件处理下载任务,小明处理其他任务,不需关注进度,只需接收软件“叮”声通知,即可】
也就是说,同步/异步是“下载完成消息”通知的方式(机制),而阻塞/非阻塞则是在等待“下载完成消息”通知过程中的状态(能不能干其他任务),在不同的场景下,同步/异步、阻塞/非阻塞的四种组合都有应用。
2.2 故事2
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
老张把水壶放到火上,立等水开。(同步阻塞)老张觉得自己有点傻。 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)。 老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。 老张把响水壶放到火上,立等水开。(异步阻塞)。 老张觉得这样傻等意义不大,老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)。 所谓同步异步,只是对于水壶而言。普通水壶,同步;响水壶,异步。虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。 所谓阻塞非阻塞,仅仅对于老张而言。立等的老张,阻塞;看电视的老张,非阻塞。 情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。
3 其它
异步跟队列有关,阻塞跟锁有关。
同步就是等待程序调用结果,阻塞时会释放cpu和资源。
同步非阻塞就是会等待结果但是线程不会被挂起,会继续占用资源。
同步阻塞就是等待结果的时候,线程被挂起了,资源和cpu别释放了,等待信号唤醒
异步就是发送方执行很多调用,不关心结果。
处理方如果等待处理结果不去执行其他东西,异步阻塞
4 处理方如果也不等待,就行执行其他的程序,就是异步非阻塞
阻塞/非阻塞核心区别就是看当前任务有没有被挂起。 在进程通信层面, 阻塞/非阻塞, 同步/异步基本是同义词, 但是需要注意区分讨论的对象是发送方还是接收方。发送方阻塞/非阻塞(同步/异步)和接收方的阻塞/非阻塞(同步/异步) 是互不影响的。 在 IO 系统调用层面( IO system call )层面, 非阻塞IO 系统调用 和 异步IO 系统调用存在着一定的差别, 它们都不会阻塞进程, 但是返回结果的方式和内容有所差别, 但是都属于非阻塞系统调用( non-blocing system call )。 阻塞和非阻塞是等待I/O的期间能不能做其他事情, 自己会不会被挂起, 是关注自己的状态,同步异步是是否需要主动询问, 描述的是行为方式(通信机制)。 非阻塞系统调用(non-blocking I/O system call 与 asynchronous I/O system call) 的存在可以用来实现线程级别的 I/O 并发, 与通过多进程实现的 I/O 并发相比可以减少内存消耗以及进程切换的开销。