网上很多这四个概念的文章,但我看起来大多是有问题的,很多都说反了。这两组概念最早来自于操作系统通信,但是对于更广泛的编程角度其实已经有变化了。
我认同Akka官网对这两组概念的解释:
Asynchronous vs. Synchronous 异步和同步
A method call is considered synchronous if the caller cannot make progress until the method returns a value or throws an exception. On the other hand, an asynchronous call allows the caller to progress after a finite number of steps, and the completion of the method may be signalled via some additional mechanism
如果一个方法被调用后,调用者只能等到此方法返回值或抛出异常才能继续前进,那这个方法就被称为是“同步”的。
而“异步”调用,是指调用者在经历有限的步骤之后,可以继续前进。方法的完成可以通过其它的机制进行通知,比如Callback, Future, 或者消息。
Non-blocking vs. Blocking 非阻塞和阻塞
We talk about blocking if the delay of one thread can indefinitely delay some of the other threads. In contrast, non-blocking means that no thread is able to indefinitely delay others.
阻塞是说一个线程可以无限期地延迟另一个线程的执行。比如使用互拆锁。非阻塞是说没有线程能够无限地阻塞其它线程。
大家搞混的原因是里面都有“等待”,但是用错地方了。同步异步是描述方法的调用,调用者必须无条件等待方法调用完成。阻塞非阻塞说的是线程之间相互影响,通常形容一个资源是否具有独占性,独占了自然其他线程必须等待。比如Java中的BlockingQueue就是阻塞队列,但是synchronized关键字代表的含义是锁更像阻塞而非同步,所以我猜测大部分人理解错同步都是因为这个关键字的原因。
其实一般编程语言的函数调用都是同步的,只不过它是否立刻能有你要的计算结果。
以 点餐例子来说明这两组的搭配:
- 同步:你把餐点好以后,在厨房盯着厨师把菜做好拿出来,你才能继续干别的。点餐这件事来说,让点餐人持续盯着就是同步,反之就是异步。
- 阻塞:厨房只有一个厨师能用,其他厨师得等,这个厨房就是阻塞的。
同步和阻塞是两个范畴的概念,盯着厨师做好菜与厨房是不是只能一个厨师用并没有关系。同步非阻塞说的就是盯着厨师直到菜好,但厨房可以多个人同时用。异步阻塞说的是不盯着继续做别的事了,厨房是轮流用的那种。
要实现异步,通常都得用其他线程来完成。一个同步的API也可以使用阻塞来实现同步,但这不是必须的。