Concurrency and Asynchronous Programming: a Detailed Overview 12 What about threads provided by the operating system? We'll cover threads a bit more when we talk about strategies for handling I/O later in this book, but I'll mention them here as well. One challenge when using OS threads to understand concurrency is that they appear to be mapped to cores. That's not necessarily a correct mental model to use, even though most operating systems will try to map one thread to one core up to the number of threads equal to the number of cores. Once we create more threads than there are cores, the OS will switch between our threads and progress each of them concurrently using its scheduler to give each thread some time to run. Y ou also must consider the fact that your program is not the only one running on the system. Other programs might spawn several threads as well, which means there will be many more threads than there are cores on the CPU. Therefore, threads can be a means to perform tasks in parallel, but they can also be a means to achieve concurrency. This brings me to the last part about concurrency. It needs to be defined in some sort of reference frame. Choosing the right reference frame When you write code that is perfectly synchronous from your perspective, stop for a second and consider how that looks from the operating system perspective. The operating system might not run your code from start to end at all. It might stop and resume your process many times. The CPU might get interrupted and handle some inputs while you think it's only focused on your task. So, synchronous execution is only an illusion. But from the perspective of you as a programmer, it's not, and that is the important takeaway: When we talk about concurrency without providing any other context, we are using you as a programmer and your code (your process) as the reference frame. If you start pondering concurrency without keeping this in the back of your head, it will get confusing very fast. The reason I'm spending so much time on this is that once you realize the importance of having the same definitions and the same reference frame, you'll start to see that some of the things you hear and learn that might seem contradictory really are not. Y ou'll just have to consider the reference frame first. Asynchronous versus concurrent So, you might wonder why we're spending all this time talking about multitasking, concurrency, and parallelism, when the book is about asynchronous programming. The main reason for this is that all these concepts are closely related to each other, and can even have the same (or overlapping) meanings, depending on the context they're used in.