Asynchronous programming is much more of a philosophy than just another programming trick. While, your last question attracted answers mainly about programming aspects and my answer was a disconnected loner for being mostly theoretical, I am trying to give you a fresh perspective building on the same line but explanations rather than just references.
This one is about some fundamentals of why and how of Asynchronous Programming.
Let's suppose you go to a bakery shop (and assuming the cake will be prepared after the order) - you have two choices, either you choose to wait till the cake is ready or you give the order and head-back to home and pick up later when it is ready. The first one (wait) is a synchronous method and later is asynchronous method. Needless to say this example provides a good reference why should you use asynchronous methods over synchronous.
Event based programming is only one of the ways the asynchronous systems can be built and it is not just a useful design pattern but rather it is an architectural pattern. I am listing down cases where this theory is used in a practically useful way - hoping that it would bring some clarity
One of the first example of Asynchronous systems are Unix system IO.
While we know
write() and even
select() calls blocks the program flow, but inside the OS, they are asynchronous, i.e. the kernel generally knows that the block device (aka hard disk) will take some time to fill buffer, till such a time CPU is free from that respective thread and hence the thread is parked as (not ready).
Refer 1. Moris Bach "The design of Unix Operating system"
Another most common example is majority of UI frameworks. Here, all user clicks are first dispatched through a controller which in turn call backs respective application. Important thing is such call backs should not keep call-backs waiting else the system will freeze. The call back from UI controller to back-ends are usually asynchronous if they involve heavy processing.
Another good example of asynchronous programming (as a pure design pattern) is Active Object. An active object is one which has it's own private thread such that one can keep many requests in a queue and execute one-by-one.
Refer to this Paper : Active Object. This pattern is heavily used right from Enterprise software to mobile frameworks. The popular platforms Java/EJB and .NET allows Local or Remote asynchronous method invocation which essentially allows normal objects to become active objects. Active objects were present way back in Symbian : Active objects in Symbian OS by Aapo Haapanen (see this also: Active Objects in Symbian). This is now also present in Android).
Apart from Active object, the same author Douglas C. Schmidt, has produced number of other works which are other parallels to Active object and are also the asynchronous patterns. See this Event Handling Patterns and a full account is available on his book Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects - V2
When a given object needs to return the API, while working in the background to actually accomplish the work, the usual methodology is to have a multi-threaded system to achieve this. Threaded systems are present everywhere from C (posix), C++ (boost) to Java, C# and so on. Active Object is essentially only an abstraction which can hide this. See why Active object implementations are preferable over naked threads. Another good read.
But this concept goes beyond threads or objects inside an application to become asynchronous. One of the best usage is in Distributed systems where two applications doesn't necessarily need to wait for each other for co-ordinations. Good old (or not so good, whichever way you look at it) RPC was synchronous. [of course, there are other asynchronous RPCs as well]. But the modern alternatives like Message Oriented Middleware is truly asynchronous for good reasons.
Last but could be most interesting one, is the Agents programming which can benefit from Asynchronous model of communication.
While asynchronous programming does look sexy but it creates its' own complexity including:
- framework for return value passing
- additional overhead of communication
- additional need for synchronizing constructs
- possibility of deadlocks, racing etc. if things not done right.
... and so on.
It should always be used only for a genuine reasons.
So when should one use Asynchronous model? When should you put a background thread and allow caller to go asynchronous?Here are some good thumb rules when it applies (but not complete)
When system wants to apply strict serious resource conversation: for example, you want to keep an absolute fixed number of threads. Asynchronous pattern forces the system to implement queue.
When caller's need to do "other useful things to do" indeed is genuine. So many times, the other thread even if made unblocking, will not do anything useful and hangs around polling for results. This indeed can be more CPU consuming than basic synchronous model.
When you need higher levels of reliability in distributed systems. (see Message Oriented Middleware).