Skip to content

Instantly share code, notes, and snippets.

@danog
Created January 5, 2024 01:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danog/f0e9103e6a7e1bcec1b92c411a3c4607 to your computer and use it in GitHub Desktop.
Save danog/f0e9103e6a7e1bcec1b92c411a3c4607 to your computer and use it in GitHub Desktop.
An overview of concurrency and parallelism

Sorry if I'm stating the obvious for some, but I feel like many people are lacking a good comprehension of what is concurrency vs parallelism, and since Operating Systems was my favorite uni exam decided to write up a small refresher, a few years after finishing it :D

Put (very) simply, a scheduler is a piece of software that schedules execution of some code on the CPU.

The OS scheduler is a preemptive scheduler that runs in the kernel and schedules OS threads for execution on the CPU.

Since there are usually many threads waiting for CPU time, and only one CPU (let's consider just single-core systems), the scheduler gives each thread a little time slice, and once that expires, it interrupts execution of the thread starts thr next one in the queue. Only one thread is physically running at any given moment, and the entire set of all active threads is considered to be running concurrently.

The ability to interrupt execution of threads even if they don't explicitly return control to the scheduler (such as by making I/O syscalls) is why the OS scheduler is called preemptive.

On multi-core processors, the OS scheduler can run multiple threads at the same time, thus allowing parellelism (as opposed to concurrency), the parallel execution of N threads on N distinct hardware CPUs.

Event loops such as node's, go's runtime, amphp or swoole are schedulers (quite like the OS scheduler) that also schedule execution of userland threads (to differentiate from OS threads, they are also called green threads (fibers), or coroutines, or goroutines) on a single OS thread. Like in a system with N OS threads and 1 CPU, scheduling N green threads on 1 OS thread means all green threads are concurrent, not parallel.

Unlike the preemptive OS scheduler, event loops are considered cooperative schedulers because unlike the OS scheduler, they cannot interrupt execution of threads unless they explicitly return control, for example by doing I/O: this can be problematic with CPU-intensive operations like cryptography, because no other green thread can be scheduled on the CPU (because unlike the OS scheduler, a cooperative scheduler cannot interrupt a running thread).

However, in reality is not a problem, because the vast majority of the time in a modern application is spent waiting for I/O (network, database queries, files), so while waiting for the result of an operation on one green thread, the cooperative scheduler (i.e. event loop) can schedule another.

Concurrent userland threads are preferable to normal OS threads for a variety of reasons, the main one being improved performance thanks to simplified context switching.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment