来自 Stackoverflow 上的两个解释：
Blocking may or may not be the same as synchronous, depending on the context. When we talk about method calls, then a synchronous call can also be said to be blocking (I'll get back to this in a bit), because the thread calling the method cannot proceed forward until the method returns. The antonym in this case would be asynchronous.
In lock terminology, a lock is said to be blocking if the thread waiting to acquire it is put in a suspended mode until the lock becomes available (or until a timeout elapses). The antonym in this case is a non-blocking lock, meaning that the thread returns immediately even if it cannot acquire the lock. This can be used to implement the so called spinning lock, where you keep polling the state of the lock while keeping the thread active.
Having said this, you can extrapolate the difference between the concepts: synchronous generally means an activity that must wait for a reply before the thread can move forward. Blocking refers to the fact that the thread is placed in a wait state (generally meaning it will not be scheduled for execution until some event occurs). From here you can conclude that a synchronous call may involve blocking behavior or may not, depending on the underlying implementation (i.e. it may also be spinning, meaning that you are simulating synchronous behavior with asynchronous calls).
Blocking - operation are said to have blocking behavior if it waits for some event to get complete. For example: if a lock is not available a thread may enter a wait state on event till lock is available. Such an operation is said to be blocking.
Synchronous - Synchronous call can be easily understood with an example of http protocol where client waits for reply from server an then proceeds. Synchronous call can be blocking or non blocking.
Asynchronous - A method can asynchronous call other method. After a call it can continue to execute its next instruction. When called method completes it execution it will send an reply/callback to caller method of it's success or failure.
Non-blocking - Non blocking behavior is like checking the condition at that instance. For example- in case of locks if it is not available it will not wait till it is available like blocking operation. Also we need to repeatedly check the availability of locks as there will be no callback like asynchronous calls.
Summary: Blocking is always synchronous.
Synchronous call have blocking operations if it waits for some event to get complete, caller method may enter wait state.
Synchronous call is non blocking, if it repeatedly check for some event to occur before proceeding for next instruction. Caller method does not enter wait state on some event to complete.
Asynchronous call cannot be blocking and it involves callback from called method which needs to handle.
The Reactor pattern allows event-driven applications to demultiplex and dispatch synchronously and serially service requests that are received simultaneously from one or more clients.
The Proactor pattern allows event-driven applications to demultiplex and dispatch service requests in an efficient asynchronous way.