同步异步和阻塞1
Posted organic
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了同步异步和阻塞1相关的知识,希望对你有一定的参考价值。
同步异步和阻塞是个有关联,但有有区别的东西。很多时候会从直觉上认为 : 同步 = 阻塞, 异步 = 非阻塞。
但实际上他们是完全描述的不同的东西:
同步异步是从request –> Receive Result这个过程的不同来讲的。
而阻塞是指在等待Request结果时,线程是否会挂起。
对于一个IO过程,可能是同步异步中的一种,同时也必然是阻塞或非阻塞。他们正交的结果共有4种:
1. 同步阻塞
request –> block –> return result
即同步调用后,当函数返回时就能得到IO的结果。
举个例子:小明去图书馆查文献(request),管理员让小明稍等,然后去系统帮小明查(阻塞,可能几分钟查到了,可能要1天才能查到),管理员查到后告诉小明(return result)。这管理员告诉小明结果之前,小明得一直等在哪里,啥也干不了,哪怕是一天。
所以这种模式最大的问题时浪费小明时间,等待特别无聊。在程序中就是浪费CPU周期。
这是一个人类最直接的过程,如我们用Internet系列函数发起HTTP请求,在调用HttpSendRequest()后,一般需要等一会才会返回结果,网络有问题时可能会等上20多s,程序在取到结果后继续向下执行,当然也有可能再发起一个另一个的HTTP请求。
优点:
- 最符合人类思维
- 实现最简单
- 没有数据同步问题
缺点:
- request返回前无法停止
- 会阻塞调用线程,当调用线程是UI线程时,会导致整个UI卡住,用户可能会以为程序挂掉了。
- 无法实现并发,如小明要查2篇文献,只能先让管理员查第一篇,然后等到结果后,再让管理员查第二篇(假设管理员一次只能查一篇文献)。小明也不能同时告诉2个管理员,因为在告诉第一个管理员的时候,必须等待其查询结果完成,小明才能干其他的。
2. 同步非阻塞
request –> polling –> return result
这是一个不容易理解的模式,同步还能非阻塞?还真能:
举个例子 : 如小明去图书馆查文献,管理员让小明稍等,小明觉得等太无聊,就跑出去玩了(非阻塞),玩一会就回来看看管理员有没有查到。
这个过程中小明没有阻塞,在等到结果前还能干其他的事,比如出去打把dota。但同步的老问题还是在,在管理员没查到前,小明还是不能回家,他打一把dota还要回来看看管理员查到没有。
这个模式在解决某些程序在处理一个request时,预处理比较耗CPU,可以在等待IO的时间内,对下一个request进行预处理,这样前一个IO完毕后,就能立即处理下一个request IO。
优点:
- request返回前可以干干别的,充分利用CPU资源
- 可以实现并发了,比如小明要查2篇文献,他可以到找管理员A(线程1)去查第一篇,然后取找管理员B(线程2)查第二篇(当然,如果只有一个管理员,那么并发就没啥意义的),然后玩一会后挨个来问管理员AB有没有查到,当管理员AB都查到后小明就可以回家了。
缺点:
- request返回前无法停止,因为轮询也会卡住调用线程
- 实现比较复杂
- 轮询不是个好设计方案,如果轮询不设间隔时间,会导致CPU高,浪费CPU,如果设置时间间隔,会导致request返回的实际比实际完成的时间要长。
3. 异步非阻塞
request –> return(no result) ------> notify result
典型的异步模式,发起request后,会立即返回(不阻塞),但此时IO并没有处理完,等IO处理完后,再通过callback的方式通知调用者。
举个例子 : 如小明去图书馆查文献(request),管理员让小明先回去(return,非阻塞),等查到了就打电话告诉小明(callback)。
异步和同步的区别就在于request返回后是否返回了IO结果。
优点:
- request返回前可以停止,如小明回去后觉得这篇文献不要了,可以和管理员说不查了,或者干脆不鸟管理员了。
- 容易实现并发
缺点:
- 线程同步是个复杂的问题。
4. 异步阻塞
异步阻塞没有意义。
5. 同步一定是单线程的吗?
不一定,如同步非阻塞中,一个同步请求中可以发起多个线程同时处理多个IO,这样可以提高效率
以上是关于同步异步和阻塞1的主要内容,如果未能解决你的问题,请参考以下文章