如何理解阻塞、非阻塞与同步、异步的区别?
2024-06-07 13:09:46
同步与异步
同步与异步关注的是消息通信机制。
●所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。
●而异步则是相反,调用在发出之后,这个调用就直接返回了,所以就没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出之后,被调用者通过“状态”、“通知”、“回调”三种途径通知调用者。
可以使用哪一种途径依赖于被调用者的实现,除非被调用者提供多种选择,否则不受调用者控制。
●如果被调用者用状态来通知,那么调用者就需要每隔一定时间检查一次,效率就很低。
●如果使用通知和回调的方式,效率则很高。因为被调用者几乎不需要做额外的操作。
举个例子:
你打电话问书店老板有没有《高效演讲》这本书。
如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。
阻塞与非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。
●阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
●非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
接着上面的例子:
打电话问书店老板有没有《高效演讲》这本书,
●如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果。
●如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了(先去干点别的,不用傻等), 当然你也要偶尔过几分钟检查一下老板有没有返回结果。
故事描述
百里爱喝茶。
出场人物:百里,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1.百里把水壶放到火上,立等水开,什么都不做,(同步阻塞)百里觉得自己有点傻。
2.百里把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)。
3.百里还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
4.百里烧水,但站在水壶前啥也不干(线程阻塞),等水壶响了(异步回调)取水。(异步阻塞)。
5.百里觉得这样傻等意义不大,百里把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)。
●同步异步,只是对于水壶而言。
○普通水壶,同步。
○响水壶,异步。
虽然都能干活,但响水壶可以在自己完工之后,提示百里水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己(情况2中),造成百里效率的低下。
●阻塞非阻塞,仅仅对于百里而言。
○立等的百里,阻塞。
○看电视的百里,非阻塞。
情况1和情况3中百里就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的百里没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。
回调函数
前面提到,回调是异步调用的一种实现方式。那么什么是回调函数呢?
●概念
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
●举个例子
概念不是太好理解,我们举个例子。
沿用上面买书的例子,你的电话号码就叫回调函数,你把电话留给书店老板就叫登记回调函数,书店老板查好了叫做触发了回调关联的事件,老板给你打电话叫做调用回调函数。你接电话叫做响应回调事件。