← Operating System Concepts

BOOK NOTES · OPERATING SYSTEMS · CHAPTER 4

Operating System Concepts Chapter 4 — Threads & Concurrency.

operating-systemschapter-4threadsconcurrencyparallelismmulticore

// the one-minute version

A thread is a single flow of execution inside a process. One process can run many threads that share its memory but each own a stack and registers. Threads make programs faster on multicore CPUs and more responsive — but the shared memory that makes them fast is exactly what makes concurrency bugs possible. This chapter also separates two confused ideas: concurrency (juggling many tasks) and parallelism (literally running at once).

A single-threaded process does one thing at a time. But a browser wants to render, run scripts, and download images at once — without a whole separate process for each. The answer is threads: many lanes of execution inside one process, sharing its memory.

01 What a thread is

A thread owns its program counter, registers, and stack — but shares the process's code, heap, globals, and open files with its siblings. That sharing is the point: threads pass data through shared memory instantly, with no IPC.

Each thread owns

Program counter, CPU registers, and a stack of local variables and call frames.

Threads share

The code, heap, global variables, and open files of their process.

think of it likeA process is an office; threads are the workers. Each has their own desk (stack) and current task (program counter), but they share the office files, supplies, and whiteboard (heap and globals). Sharing makes them fast to collaborate — and prone to scribbling over each other's notes.

02 Why threads

Four classic benefits: responsiveness (one thread runs the UI while another does slow work), resource sharing (threads share memory for free, unlike processes), economy (creating a thread is far cheaper than a whole process — no new address space), and scalability (threads run on different cores in parallel).

03 Concurrency vs parallelism

These sound alike but aren't. Concurrency means dealing with many tasks all in progress — even on one core, by interleaving. Parallelism means literally executing multiple tasks at the same instant, which needs multiple cores.

key ideaA single-core machine can be concurrent but never parallel. A multicore machine can be both. Concurrency is about structure (juggling tasks); parallelism is about execution (truly simultaneous). You can have one without the other.

04 How much can parallelism help? Amdahl's law

Throwing more cores at a program has a hard ceiling, captured by Amdahl's law: the speedup is limited by the fraction of the work that must run serially. If 25% of a job is inherently sequential, then even with infinite cores you can never go more than 4× faster — that serial quarter dominates. The lesson: parallel hardware only pays off if the algorithm is mostly parallelizable.

05 User threads vs kernel threads

User-level threads are managed by a library in user space — fast to create and switch, but the kernel sees only one process, so one blocking system call can stall them all. Kernel-level threads are managed by the OS — it can schedule them on separate cores and one block won't freeze the rest, at the cost of more overhead per operation.

06 Multithreading models

How user threads map onto kernel threads gives three classic models:

ModelMappingTrade-off
Many-to-onemany user → 1 kernel threadfast, but one block stalls all; no true parallelism
One-to-oneeach user → its own kernel threadreal parallelism & isolation; more overhead per thread
Many-to-manymany user → smaller pool of kernel threadsflexible balance; more complex to implement
noteMost modern systems (Linux, Windows) use one-to-one — every thread you create is a real kernel thread. It's simple, gives true multicore parallelism, and threads are cheap enough now that the overhead rarely matters.

07 Thread pools

Creating a fresh thread per task is wasteful and unbounded. A thread pool keeps a fixed set of workers alive and feeds them tasks from a queue. It caps how many threads exist (protecting against overload) and skips repeated creation cost. This is how web servers handle thousands of requests with a handful of workers.

08 The dark side: implicit threading and data races

Because threads share memory, two threads touching the same data without coordination create a race condition — a bug that depends on timing and may appear once in a million runs. Other hazards include deadlock (Chapter 8) and the difficulty of dividing work and balancing it across cores. Modern frameworks lean on implicit threading (thread pools, fork-join, OpenMP) to let the runtime manage threads so programmers make fewer of these mistakes — but the underlying dangers remain.

watch outMore threads is not always faster. Past the number of cores, extra threads add context-switching and contention, slowing things down. And the instant two threads write shared data without synchronization, you have a race condition — the entire subject of the next two chapters.

common catches & gotchas

  • Concurrency ≠ parallelism — One core interleaves (concurrent) but never runs two things at the same instant (parallel). Mixing these up is the most common Chapter 4 error.
  • Threads share the heap, not the stack — Local variables are private per thread; heap and globals are shared. Bugs come from assuming the wrong one.
  • Amdahl's law caps speedup — A mostly-serial program barely benefits from more cores. Don't promise linear speedup.
  • User threads can block each other — With many-to-one, one blocking system call freezes every user thread, because the kernel sees just one schedulable entity.
  • More threads can be slower — Beyond core count, threads fight for the CPU and caches. Thread pools exist partly to stop this.

09 Questions students actually ask

What's the core difference between a thread and a process?

Processes have separate memory; threads in one process share memory. That makes threads cheaper and faster to coordinate, but a bug in one thread can corrupt data the others rely on.

Can I get parallelism on a single-core CPU?

No. One core runs one instruction stream at a time, so you only get concurrency (fast interleaving). True parallelism needs multiple cores.

What does Amdahl's law tell me?

Speedup from more cores is capped by the serial fraction of the work. If 25% must run sequentially, the maximum speedup is 4×, no matter how many cores you add.

Why do most systems use one-to-one threading?

It gives real multicore parallelism and keeps one blocked thread from freezing the others, and modern kernel threads are cheap enough that the overhead is acceptable.

Why use a thread pool instead of making threads on demand?

To cap the total number of threads (so a flood of work can't exhaust the system) and to avoid paying thread-creation cost repeatedly. The pool reuses a fixed set of workers.

10 Key takeaways

  • A thread is a flow of execution; threads share their process's memory but own stack and registers.
  • Threads add responsiveness, cheap sharing, low cost, and multicore scalability.
  • Concurrency = juggling tasks; parallelism = running them at once. Different ideas.
  • Amdahl's law: the serial fraction caps the speedup from more cores.
  • User threads are fast but kernel-blind; kernel threads get real scheduling at more cost.
  • Models: many-to-one, one-to-one (the common choice), many-to-many.
  • Thread pools bound and reuse workers — but shared memory means race conditions.

11 Wrapping up

Threads are how one program uses many cores and stays responsive. The power — shared memory — is also the danger, which is why scheduling and then synchronization come next. Next up: CPU Scheduling.

← prev: Chapter 3next: Chapter 5 →
© cvam — written in plaintext, served warm