Synchronous vs. asynchronous communications
Synchronous communications require some type of "handshaking" between tasks that are sharing data. This can be explicitly structured in code by the programmer, or it may happen at a lower level unknown to the programmer.
Synchronous communications are often referred to as blocking communications since other work must wait until the communications have completed.
Asynchronous communications allow tasks to transfer data independently from one another. For example, task 1 can prepare and send a message to task 2, and then immediately begin doing other work. When task 2 actually receives the data doesn't matter.
Asynchronous communications are often referred to as non-blocking communications since other work can be done while the communications are taking place.
Interleaving computation with communication is the single greatest benefit for using asynchronous communications.