Asynchronous programming is not something you spend much time thinking about. Yes, believe me. Just start analysing the requirements in the developer's eye, keeping in mind that you want to develop a resource and time efficient application.
Laying the groundwork, In the Developer's Eyes
Scenario 1: As a developer, I want to continue the execution of code to the next line instead of getting stuck or waiting for the completion/result of long-running code (for example network or database operations).
Example case: A long-running execution happens and instead of waiting for the completion/result, we want to continue further without wasting time.
Scenario 2: As a developer, I want to finish a task, time-efficiently and utilizing other available cores of CPUs or machines by dividing the task into independent chunks.
Example case: Modern CPUs have multiple cores and at a single moment, only one core is being used to execute a task. Here, we want to utilize the other cores of CPU by distributing the job.
Mechanism to do the preceding
Well, now we have 2 valid ideas to boost the performance of an application. For the implementation of these ideas we need some special mechanism in coding. And these mechanisms are known as asynchronous and parallel programming respectively. :) So far easy? Good. :)
Asynchronously means non-blocking, in other words you can proceed without waiting on a long-running line of code. For example, to get a task done, if you have written 4 lines of code in which the second line is a time-consuming method call (maybe related to network I/O or a database call). Now, you want to apply some mechanism in your third line to begin execution without waiting for the completion or result of your second line. This is the non-blocking style.
Getting to the second scenario, just think that if you can break your task into independent pieces of work, then what? Would you not like to get these independent pieces of work done in parallel to finish faster? This is called parallelism. In this case there must be available free resources to do the job in parallel. (A resource could be cores of a CPU or even multiple machines.)
Ahh! You must clearly understand the requirements of these 2 mechanisms in programming. So far we have concluded that these two approaches enable us to finish our task faster (utilizing the wait-time and free-resource).
Let's clarify the things with more technical terms :)
If we say that asynchronous provides no wait time and continuous execution of the code then this line itself clarifies that we are talking about single-threaded processing. It also makes clear that it is all about a "concurrent work" fashion.
Concurrent? In a single-threaded process, at the same time, many lines of code can be executed concurrently. To do this, Async and Callbacks mechanisms are used. It involves heavy Context Switching and Time Scheduling.
* You can conclude at this point that: "An Asynchronous Task might use Parallelism".
In the case of parallel programming, there must be multiple threads, otherwise how can that be processed/done in parallel. In this case the programmer needs to have more control over threads/cores of CPUs in a precise manner.
Asynchronous: Hey you, do this task and return with the results. Meanwhile I will get done other tasks. (No wastiing of time. :))
Parallel: Hey you, do this task and return with the results. Meanwhile I will do nothing but wait for you. You can smartly use other free resources/cores of the CPUs/machines to boost the work time.
Parallel programming is like developers (a team) working on a project module with a common goal to complete the task (project module job work). :)