What Are the Different Types of Concurrency?
The main types of concurrency are thread-based, process-based and event-driven (asynchronous) concurrency, each of which can be preemptive or cooperative, and each of which can split work by data or by task. Two more categories appear in specific settings: distributed concurrency across machines, and concurrency control inside databases, which is either optimistic or pessimistic.
Concurrency means that several tasks are in progress during the same period. Parallelism means that several tasks execute in the same instant on different cores. A single-core machine can be concurrent but never parallel. An 8-core machine running 8 threads is both.
The types in one table
| Type | Unit of work | Shares memory? | Who switches | Example |
|---|---|---|---|---|
| Thread-based | Thread inside a process | Yes | OS scheduler (preemptive) | A web server with a pool of 200 worker threads |
| Process-based | Separate process | No, uses pipes or sockets | OS scheduler (preemptive) | PostgreSQL, one process per connection |
| Event-driven (async) | Task or coroutine on an event loop | Yes | The task itself, at await (cooperative) | Node.js, Python asyncio, browser JavaScript |
| Data parallelism | Same operation on chunks of data | Usually yes | Runtime or library | Summing a large array with one thread per chunk |
| Task parallelism | Different operations at once | Usually yes | Runtime or library | Compressing one file while encrypting another |
| Distributed | Process on another machine | No, uses the network | Each machine's own scheduler | A microservice calling three other services |
| Real-time | Task with a deadline | Varies | Priority scheduler | Engine control unit in a car |
Thread-based, process-based and event-driven
Thread-based concurrency runs several threads inside one process. They share the same heap, so passing data is free, and so is corrupting it. A thread that writes to a map while another reads it produces a data race. Locks, atomics and thread-safe collections exist to prevent that. Java, C++, C# and Go programs use this model most of the time.
Process-based concurrency runs several processes, each with its own memory. A crash or a memory leak in one process does not affect the others, and there are no data races. Communication costs more, because data has to be copied through a pipe, a socket or shared memory. Python uses processes for CPU-bound work because of its global interpreter lock, and PostgreSQL uses one process per client connection.
Event-driven concurrency runs many tasks on one thread with an event loop. A task runs until it needs to wait, typically for a network reply, and then yields. The loop runs another task in the meantime. There is no parallelism on a single loop, but there is also no lock contention, and tens of thousands of idle connections cost almost nothing. Node.js, nginx and Python asyncio are built this way.
Preemptive and cooperative concurrency
In preemptive concurrency, the scheduler can interrupt a task at any point. Operating system threads work this way. A task cannot starve the others by running forever, but any line of code may be interrupted, so shared data needs locks.
In cooperative concurrency, a task runs until it yields. Coroutines and async functions work this way: the only switch points are the await expressions. Code between two awaits cannot be interrupted, which removes many locks. The cost is that one long computation without an await blocks every other task on that loop.
Data parallelism and task parallelism
Data parallelism applies the same operation to many pieces of data at once. Rendering an image splits the pixels across threads. A parallel sort splits the array. GPUs are data-parallel machines with thousands of small cores. The work divides evenly, so the speedup is close to the core count.
Task parallelism runs different operations at the same time. A build tool compiles one file while it links another. A game runs physics on one thread and audio on another. The tasks differ in length, so one long task can leave other cores idle.
Distributed and real-time concurrency
Distributed concurrency spreads tasks across machines that talk over a network. Nothing is shared, messages can be lost or delayed, and any machine can fail while the others continue. The problems change from data races to partial failure, ordering and consensus.
Real-time concurrency adds deadlines. A hard real-time task, such as a brake controller, must finish within its deadline every time, and the scheduler is chosen to guarantee that. A soft real-time task, such as video playback, may miss an occasional deadline with reduced quality.
Concurrency control in databases: optimistic and pessimistic
Databases face concurrency from many clients writing the same rows. Pessimistic concurrency control locks a row before reading it, so a second writer waits. It is safe under heavy contention but reduces throughput. Optimistic concurrency control lets everyone proceed and checks for conflicts at commit time, usually by comparing a version number. If the version changed, the write is rejected and the client retries.
MongoDB's WiredTiger storage engine uses optimistic concurrency control internally, with document-level conflict detection and a transparent retry. At the application level, the same pattern is a version field in the document.
db.orders.updateOne( { _id: orderId, version: 7 }, { $set: { status: "shipped" }, $inc: { version: 1 } } )
If matchedCount is 0, another writer changed the document first, and the application reads it again before retrying.
How to Prepare
Interviewers use this question to check whether you can pick a model for a given problem, not to hear the list.
- Match each type to one problem it fits. Threads for a CPU-bound server, an event loop for many idle connections, processes for isolation, optimistic control for low-conflict database writes.
- Explain the trade-off in each pair. Preemptive against cooperative, threads against processes, optimistic against pessimistic.
- Code one of them. A bounded queue with two threads is the most common request.
Grokking Multithreading and Concurrency for Coding Interviews covers the thread-based model in depth with coded exercises.
Grokking System Design Fundamentals covers distributed concurrency and database concurrency control.
Grokking the System Design Interview applies both to full system design questions.

GET YOUR FREE
Coding Questions Catalog

$99

$197

$72