The concepts of asynchronous and non-blocking have been around from a very long time, but the term asynchronous really started becoming really popular when AJAX began being used in mainstream web development. Similarly non-blocking started to become popular when Java introduced the non blocking API’s for I/O, but it really took steam when node.js bought it to the world of server side development.
Both these concepts (synchronous/asynchronous vs. blocking/non-blocking) are very similar but they do have a few clear differences which not many developers know about. In this article I will discuss how these concepts relate to each other.
I’ll begin with a brief description of their opposites: that is synchronous and blocking.
Understanding what synchronous means should be fairly easy for web developers because HTTP is a synchronous protocol. The web browser sends a request to the server and waits for its response. Then it sends the next request and again waits for its response, and so on. Having to wait for the response before sending the next request is often a pretty huge bottleneck.
The concept of blocking is also easy to understand. Let’s see the description of Java’s InputStream.read method (used to read files):
If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
This call is called blocking because it will wait for the input data to become available. This too can create performance bottlenecks because the thread on which the call is made will stop from further execution.
Asynchronous and non-blocking I/O are the opposites of synchronous and blocking. In a sense both are fairly similar in that they allow your code to make an API call in a way that does not hold up the entire thread of execution. But they are also different because asynchronous calls usually involve a callback or an event, to signal that the response is available, while in the case of non-blocking the call returns with whatever is available and the caller might have to try again to get the rest of the data. The word non-blocking is usually used with I/O, while asynchronous is used in a more generic sense with a broader range of operations.
In particular, asynchronous I/O, in full generality, means I/O that is done independently of the current flow of execution. — Source
And here’s a more specific example of asynchronous I/O:
Let’s postulate that "synchronous I/O" means to issue an I/O command and then waiting until the I/O command completes. Thus, if you issue a read command then the flow of execution will wait until something is actually read. (Your thread will block until the read operation can be fulfilled.) Then asynchronous I/O would mean "not synchronous I/O". That is, you issue an I/O command and it will be completed at some later time. It follows that to do asynchronous I/O you need an interface that allows you to issue I/O commands without blocking and to notify you when the I/O operation is completed.
An example I can think of is POSIX’s select() interface. It should be relatively easy to write wrapper code around it such that reads and writes from and to a number of file descriptors are queued and then when those operations are completed events would be generated. What happens to those events can vary depending on the interface’s design goals. An obvious choice would be to call any callback functions that the user of such an interface may have provided. — Source
Non-blocking on the other hand is explained with this nice analogy in this StackOverflow answer:
This term is mostly used with IO. What this means is that when you make a system call, it will return immediately with whatever result it has without putting your thread to sleep (with high probability). For example non-blocking read/write calls return with whatever they can do and expect caller to execute the call again. try_lock for example is non-blocking call. It will lock only if lock can be acquired. Usual semantics for systems calls is blocking. read will wait until it has some data and put calling thread to sleep.
Now that we’ve understood both the concepts in more detail, here’s a neat real world example which clearly brings out the difference between the two:
For example in the classic sockets API, a non-blocking socket is one that simply returns immediately with a special "would block" error message, wherever a blocking socket would have blocked. You have to use a separate function such as select or poll to find out when is a good time to retry.
But asynchronous sockets (as supported by Windows sockets), or the asynchronous IO pattern used in .NET, are more convenient. You call a method to start an operation, and the framework calls you back when it’s done. Even here, there are basic differences. Asynchronous Win32 sockets "marshal" their results onto a specific GUI thread by passing Window messages, whereas .NET asynchronous IO is free-threaded (you don’t know what thread your callback will be called on). — Source
I hope this article helped you understand the difference between two seemingly similar concepts of asynch and non-blocking. Now you will have an answer if you are asked this question in an interview 🙂