To put it simply, we can say that multithreading means that a program is running parallel on multiple threads. In asynchronous programming, a unit of work runs separately from the main application thread, and it tells the calling thread that the task has completed, failed, or is in progress. The interesting issues to consider around asynchronous programming are when we should use it and what its benefits are.
The potential for more than one thread to access the same shared data and update it with unpredictable results can be referred to as a race condition. We have already discussed race condition in Chapter 4, Implementing Design Patterns - Basics Part 2.
Consider the scenario we discussed in the previous section, in which people from a queue are collecting their tickets. Let's try to capture this scenario in a multithreading program...