Sikau

Operating systems · Day 9 · about 40 min

Race conditions

Why counter++ isn't safe with threads — explored by trying every interleaving.

1 + 1 = 1

Two threads share memory. Each runs counter++, which is really three steps: load, add, store. If the scheduler switches threads in the middle, one update can overwrite the other — a race condition. Such bugs appear only sometimes, which makes them nasty.

// Each thread runs counter++ as three machine steps.
function runSchedule(schedule) {
  let counter = 0;
  const reg = { A: 0, B: 0 };
  const pc = { A: 0, B: 0 };
  for (const t of schedule) {
    if (pc[t] === 0) reg[t] = counter;        // load
    else if (pc[t] === 1) reg[t] = reg[t] + 1; // add
    else if (pc[t] === 2) counter = reg[t];    // store
    pc[t]++;
  }
  return counter;
}

function allSchedules(a, b) {
  if (a === 0) return ["B".repeat(b)];
  if (b === 0) return ["A".repeat(a)];
  return [...allSchedules(a - 1, b).map((s) => "A" + s), ...allSchedules(a, b - 1).map((s) => "B" + s)];
}

function outcomes() {
  return [...new Set(allSchedules(3, 3).map(runSchedule))].sort();
}

Counting interleavings

Race conditions are among the hardest bugs in software: they hide in testing, appear under load and vanish when you look closely. Understanding exactly how updates get lost is the first step to preventing them.

Two threads with three steps each can be interleaved in 20 different orders (choose which 3 of the 6 slots belong to thread A). Some orders run one increment completely before the other and give 2. Others let both threads load 0 before either stores, and the counter ends at 1. Trying every interleaving is how model checkers find these bugs reliably.

// A: load add store   B: load add store
// "AAABBB" → A finishes first             → 2
// "ABABAB" → both load 0, both store 1     → 1
// "AABBBA" → A loads 0, B runs fully (1),
//             A stores its stale 1         → 1

The rest of this lesson

  • Making it safeexplain
  • Interleave itpredict
  • Which schedule loses an update?predict
  • Find every outcomewrite code
  • Synchronisation toolsmatch
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 12 lessons of Operating systems