Concurrency vs parallelism

Multithreading · lesson 30 of 38 · 3 min read

Two different ideas: making progress on many tasks, and truly running them in the same instant.

Open this lesson in the learning hub

Key points

  • A process owns its own memory. A thread is one line of execution inside it, and all threads of a process share the heap.
  • Concurrency is structure: several tasks in flight, taking turns. A single core is enough for it.
  • Parallelism is hardware: several tasks executing in the very same instant, one per core. It needs more than one core.
  • Waiting work overlaps beautifully, because a thread blocked on the network or a disk is using no CPU at all.
  • CPU work does not overlap. Past the core count, extra threads only add context switches, and each one costs microseconds.

Example

public class Main {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("cores available  : " + Runtime.getRuntime().availableProcessors());

        // Concurrency: two jobs that only wait overlap, even on a single core.
        long t0 = System.nanoTime();
        Thread a = new Thread(() -> waitFor(200));
        Thread b = new Thread(() -> waitFor(200));
        a.start(); b.start();
        a.join();  b.join();
        System.out.println("2 waiting jobs   : " + ms(t0) + " ms (not 400: waiting overlaps)");

        // Parallelism: the same CPU work, once on one thread and once on two.
        long t1 = System.nanoTime();
        long serial = burn(0, 200_000_000);
        System.out.println("1 busy thread    : " + ms(t1) + " ms");

        long[] half = new long[2];
        long t2 = System.nanoTime();
        Thread c = new Thread(() -> half[0] = burn(0, 100_000_000));
        Thread d = new Thread(() -> half[1] = burn(100_000_000, 200_000_000));
        c.start(); d.start();
        c.join();  d.join();
        System.out.println("2 busy threads   : " + ms(t2) + " ms, same total = " + (half[0] + half[1] == serial));
        System.out.println("concurrency = taking turns; parallelism needs a second core");
    }

    static long burn(long from, long to) { long s = 0; for (long i = from; i < to; i++) s += i % 7; return s; }
    static void waitFor(long ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }
    static long ms(long startNanos) { return (System.nanoTime() - startNanos) / 1_000_000; }
}

Concurrency is how you structure the work. Parallelism is the machine doing it at once.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.