阻塞非阻塞同步异步
同步与异步的关系,关键在于消息机制。同步与异步看主动的是谁,对于同步,主动地是调用方,因为发出一个功能调用,没有得到结果之前,调用是不返回的。例如,只有你处理了消息,你才返回,主动方是我,因为我主动监督你。
对于异步,主动方是你,因为是你处理完了之后,通过一些机制告诉我,你要返回了。
正因如此,在同步中,如果你不返回,我就没法进行后续操作。
看一个例子:1940 年,我是一名党的高级特工,受组织派遣,深入敌后,展开卧底行动。
同步:组织在得到我的结果前,不做事情,等待我的结果,然后做出行动;
异步:组织可以去干一些不依赖我结果的事情,截个道啊,抢个仓啊:
状态:我和组织约定,以城门楼子的旗号为信号,白旗,鬼子要扫荡,黄旗,鬼子出城了,组织安排个人每天看看旗子,哎,效率肯定不行。
通知:鬼子出动了,我拿出 iphone,直接 call 我的上级领导,他们就做好准备开打。
回调:组织早做好准备了,我这完了,直接去做那些准备好的事情了。
在异步消息通知机制中,等待消息者(在这个例子中就是等待办理业务的人)往往注册一个回调机制,在所等待的事件被触发时由触发机制(在这里是柜台的人)通过某种机制(在这里是写在小纸条上的号码)找到等待该事件的人。
在 select/poll 等 IO 多路复用机制中就是 fd,当消息被触发时,触发机制通过 fd 找到处理该 fd 的处理函数。
阻塞非阻塞:
是程序等待消息时候的状态。
阻塞是说你还没返回结果之前,我会挂起线程。函数得到结果才返回。与同步的不同就是,同步的时候很多时候线程不会挂起哦!
非阻塞是说,不能立刻得到结果之前,函数不会阻塞线程,而是会立刻返回。
继续上面的那个例子,不论是叫个人天天蹲着等消息,还是使用 call 等待通知,如果在这个等待的过程中,等待者除了等待消息之外不能做其它的事情,那么该机制就是阻塞的。
表现在程序中,也就是该程序一直阻塞在该函数调用处不能继续往下执行, 相反,在等待的时候我们可以磨磨枪,埋埋雷,,这样的状态就是非阻塞的,因为他(等待者)没有阻塞在这个消息通知上,而是一边做自己的事情一边等待。
同步阻塞形式:
效率是最低的,拿上面的例子来说,就是你专心等待,什么别的事都不做。实际程序中就是未对 fd 设置 O_NONBLOCK 标志位的 read/write 操作。
异步阻塞形式:
异步操作是可以被阻塞住的,只不过它不是在处理消息时阻塞,而是在等待消息被触发时被阻塞,比如 select 函数,假如传入的最后一个 timeout 参数为 NULL,那么如果所关注的事件没有一个被触发,程序就会一直阻塞在这个 select 调用处。
同步非阻塞形式:
实际上是效率低下的,想象一下你一边做着事情一边看消息到了没有,如果把磨枪和观察消息是程序的两个操作的话,这个程序需要在这两种不同的行为之间来回的切换,效率可想而知是低下的;很多人会写阻塞的 read/write 操作,但是别忘了可以对 fd 设置 O_NONBLOCK 标志位,这样就可以将同步操作变成非阻塞的了。
同步:我会等待你返回结果,非阻塞,但是我没有卡主线程,所以我不是看你返回结果没有,而是反复问你你好了没有。