7 routes42 sections324 units

Unit 2.1 · about 3 h

240 / 324

Threads, interleavings and memory consistency

Programming's asyncio queues and TaskGroup assume threads and tasks already exist. This unit goes one level down to the mechanism they rest on: preemptive scheduling of threads over shared memory. It assumes programming/concurrency-profiling-operations concurrency-models-gil as background and does not re-teach async tasks.

  • explain

You can now

  • Explain how threads share an address space while processes isolate state, and what that sharing exposes to scheduling.
  • Enumerate the legal interleavings of a two-thread increment and name the schedules that lose an update.
  • Define atomicity, visibility and ordering, and state which guarantees a lock supplies beyond mutual exclusion.

Covers

  • Threads versus processes and shared versus isolated state
  • Scheduling, interleavings, preemption and critical sections
  • Atomicity, visibility, ordering and memory consistency vocabulary

Study, in this order

4 steps

  1. Threads: shared state and uncontrolled scheduling
    Operating Systems: Three Easy Pieces - concurrency

    Sections 26.1 to 26.5: why threads share state, the shared-data example, uncontrolled scheduling and the wish for atomicity

  2. Thread API: creation, joining and build flags
    Operating Systems: Three Easy Pieces - concurrency

    Sections 27.1, 27.2 and 27.5, including the build line gcc -o main main.c -Wall -pthread

  3. Processes vs Threads
    AlgoMaster Concurrency lessons

    What is a Process? and What is a Thread?: shared address space against isolated state

  4. Race Conditions and Critical Sections
    AlgoMaster Concurrency lessons

    The Shared Counter Problem; Why count++ Is Not One Step; What is a Race Condition; Race Condition vs Data Race

Focus on

  • Threads of one process share code, heap, globals and file descriptors; each thread keeps its own registers, stack and program counter. A process boundary isolates memory, a thread boundary does not.
  • count++ compiles to load, add and store. Any preemption or parallel execution between those steps can discard one thread's update. The compiler may also collapse the whole loop at -O2; the races unit measures that case.
  • Atomicity means no visible intermediate state. Visibility means a write becomes observable to another thread. Ordering constrains which orders are observable. A mutex supplies all three for its critical section; a bare flag supplies none.

Reproduce closed-book

Closed-book, write the read, add and write table for two threads incrementing a shared counter from 5. Show one schedule that ends at 6 and state what each thread read. Then state, from the brute-force count, how many of the 20 legal orders of the six steps end at 6 and how many end at 7.

Traps

  • One run's exact total proves nothing. Optimization level, core placement and timing decide what you see; ThreadSanitizer decides whether a race exists.
  • Threads and processes do not differ only in creation cost. The defining difference is shared against isolated address space and what must be synchronized as a result.
  • Atomicity, visibility and ordering are three distinct guarantees. Making a flag visible does not make a read-modify-write atomic.

Practice

OSTEP Chapter 26 simulation: `loop.s`, `looping-race-nolock.s` and `wait-for-me.s`

threads-intro folder: run x86.py on loop.s, looping-race-nolock.s and wait-for-me.s and answer the chapter's homework questions 1 to 10, including the critical-section question 6

Predict each trace on paper first, then check it with the -c flag.

Self-test

  1. Two threads each run read, add, write on a counter holding 5. Which final values are possible, and how do the 20 legal orders split?

  2. What state do threads share after pthread_create, and what stays private?

  3. Why does OSTEP Section 27.5 put -pthread on the build line?

  4. A learner says visibility follows from atomicity. What is the counterexample?

Completion criterion

Stop when

You can write the 5-to-6 table from memory, explain the 18-to-2 split, and predict the simulator traces for all ten chapter questions before checking them.

Mark passed, then open 2.2 Only mark this when you can do it without notes.

Leads to

Resources for this unit

  • Operating Systems: Three Easy Pieces - concurrency
    Remzi and Andrea Arpaci-Dusseauprimarytheory
    Read Chapters 26-33 in order: threads, thread API, locks, locked data structures, condition variables, semaphores, bugs and event-based concurrency. Write the safety and liveness invariant before reading each worked pattern.
  • AlgoMaster Concurrency lessons
    AlgoMastersupportcourse
    Use the named lessons only: Processes vs Threads, Race Conditions and Critical Sections, Mutex, Condition Variables, Compare-And-Swap, Atomic Operations, Semaphores, Producer-Consumer Pattern, Bounded Buffer, Design Thread-Safe Blocking Queue, Barriers and Latches, Read-Write Locks, Coarse-grained vs Fine-grained Locking, Deadlock, Livelock, Starvation, Priority Inversion, Lost Signal/Wakeup, Spurious Wakeup, Concurrency Models and Thread Pool Pattern. Each unit names its lessons; read no other chapter for this section.

Also in this section

  • OSTEP concurrency homework and code
    OSTEP authorsrequiredpractice
    Use x86.py and the main, vector, condition-variable and semaphore exercises to enumerate schedules. Preserve one lost update, one deadlock and one lost wakeup as minimized tests, then repair each invariant.
  • AlgoMaster Concurrency - four bounded contracts
    AlgoMasterrequiredpractice
    Attempt Design a Closable Bounded Queue, Design Thread-Safe Rate Limiter, Design a Deadlock-Free Two-Key Executor, Design an Atomic Maximum With Compare-and-Swap, Design Deferred Callback Executor and Design Task Scheduler with Dependencies. For each, add a changed input, a deterministic failure schedule and an independent stress test outside the platform.
  • MIT 6.1810 - locks and parallelism
    MIT PDOSdepthcourse
    Use Lectures 12-14 and one lock-lab exercise only after the user-space bounded queue passes. Measure the contention change and explain the invariant preserved by the revised locking scheme.
  • Linux man-pages: pthreads and futex
    Linux man-pages projectreferencereference
    Look up the exact pthread mutex, condition variable, barrier, cancellation and timed-wait contracts plus futex(2) and pthreads(7). Read the stated pages; do not browse the whole manual.
  • cppreference: C atomic operations
    cppreferencereferencereference
    Read atomic_compare_exchange for success and failure semantics and the expected-pointer update rule, and memory_order for the six orderings and what relaxed permits. Stop before lock-free-property macros.
  • GCC __atomic builtins
    GNU Compiler Collectionreferencereference
    Read __atomic_compare_exchange, __atomic_load and __atomic_store for the expected-pointer update rule and the __ATOMIC_RELAXED constant used by the CAS reproduce step.
  • The Little Book of Semaphores
    Green Tea Presssupportbook
    Use the rendezvous, barrier and reader-writer puzzles as extra semaphore practice after OSTEP Chapter 31. Skip the Python event material; this section works in C with pthreads.

Quick find

Search Michi

Type to search every route, section, unit, topic and resource.

Enter opens the first result Esc closes

Reference

Keyboard shortcuts

n
Continue to the first unit not passed
j / k
Next / previous unit
1 2 3
Toggle learned, practised, passed
/
Open search
?
Show this help
Esc
Close open panels