Skip to content

Q043. What is the difference between concurrency and parallelism?

Short Answer

Concurrency means multiple activities can make progress during overlapping periods; parallelism means multiple activities execute at the same instant on different processing resources. A single-threaded async runtime is concurrent but not CPU-parallel. A multi-threaded workload may be both. Concurrency is primarily a program structure and coordination problem, while parallelism is an execution and throughput property.

Deep Dive

Concurrent code divides work into independently progressing units and defines how they communicate, wait, and cancel. The scheduler may interleave those units on one thread. This is valuable for I/O-bound servers because one task can run while another waits for a socket or timer.

Parallel code executes work simultaneously, usually on multiple cores. This can reduce latency or increase throughput for CPU-bound work, but it introduces synchronization, partitioning, and load-balancing costs.

Async Rust provides concurrency but does not automatically make CPU-heavy work parallel. Tokio's multi-thread runtime can schedule independent ready tasks on several workers, but blocking or CPU-intensive work still needs deliberate isolation and often a CPU-oriented pool such as Rayon.

Internal Model

An OS scheduler time-slices runnable threads and may place them on different cores. An async executor polls ready tasks; a task that returns Pending yields its worker until a wake-up schedules it again.

Whether work is parallel depends on how many executor workers or OS threads are actually running and whether the work can proceed independently.

Example

rust
use std::thread;
use std::time::Duration;

fn main() {
    let first = thread::spawn(|| {
        thread::sleep(Duration::from_millis(10));
        20
    });
    let second = thread::spawn(|| 22);

    assert_eq!(first.join().unwrap() + second.join().unwrap(), 42);
}

Common Mistakes

  • Using concurrency and parallelism as synonyms.
  • Assuming async code always uses multiple CPU cores.
  • Running CPU-bound loops as ordinary async tasks and expecting improved throughput.

Follow-ups

  • Can concurrent code run on one OS thread?
  • When should CPU-bound work use Rayon instead of Tokio?
  • How do contention and false sharing limit parallel speedup?

References

  • Rust Standard Library
  • Async Book
  • Tokio Documentation