Software-Only Mutual Exclusion Solutions

College Depth 69 in the knowledge graph I know this Set as goal
Unlocks 1 downstream topic
synchronization mutual-exclusion software

Core Idea

Peterson's and Dekker's algorithms solve the two-process critical section problem using only shared variables (flags, turn). While theoretically important, they are impractical on modern CPUs due to weak memory ordering; hardware support is essential in practice.

Explainer

From the critical section problem, you know the three requirements any solution must satisfy: mutual exclusion (at most one process in the critical section at a time), progress (if no process is in the critical section and some want to enter, one must be allowed in), and bounded waiting (no process waits forever). The challenge of software-only solutions is meeting all three requirements using nothing but ordinary shared variables — no special hardware instructions, no OS support, just reads and writes to memory.

Peterson's algorithm for two processes uses two shared variables: a boolean array `flag[2]` where `flag[i]` means "process i wants to enter," and a `turn` variable that breaks ties. When process 0 wants to enter, it sets `flag[0] = true` (announcing interest), then sets `turn = 1` (yielding priority to the other process), then waits in a loop while `flag[1] == true AND turn == 1`. The key insight is the combination: setting your flag shows intent, but setting turn to the *other* process's ID is an act of deference. If both processes try to enter simultaneously, both set their flags and both set turn — but turn can only hold one value, so whoever wrote to it *last* will be the one who waits. This guarantees mutual exclusion. Progress holds because a process only waits when the other is genuinely interested and has priority. Bounded waiting holds because after the other process exits and re-enters, it resets turn, giving priority back.

Dekker's algorithm is historically the first correct software solution, predating Peterson's. It uses the same flag array but handles tie-breaking differently — the losing process must retract its flag, wait, then re-announce interest. Peterson's algorithm is simpler and more elegant, which is why it is the version taught in most courses. Both algorithms extend the failed attempts you may have seen: using just a turn variable (violates progress — a process that does not want to enter blocks the other), or using just flags without turn (allows both to enter simultaneously if they set flags at the same time).

The fatal limitation of these algorithms on modern hardware is memory reordering. Modern CPUs and compilers aggressively reorder reads and writes for performance. Peterson's algorithm depends on a specific ordering: the flag write must become visible to the other process *before* the turn read. If the CPU reorders these operations, both processes can read stale values and both enter the critical section — mutual exclusion breaks. This is not a theoretical concern; it happens reliably on x86, ARM, and other architectures. To fix this, you would need memory barriers (fence instructions) — but those are hardware support, which defeats the purpose of a software-only solution. This is why Peterson's and Dekker's algorithms are taught for their theoretical elegance in proving that mutual exclusion *can* be solved without hardware support, while real systems use atomic instructions like test-and-set, compare-and-swap, or OS-provided synchronization primitives.

Practice Questions 5 questions

Prerequisite Chain

Counting to 10Counting to 20Understanding ZeroThe Number ZeroCounting to FiveOne-to-One CorrespondenceCombining Small Groups Within 5Addition Within 10Addition Within 20Two-Digit Addition Without RegroupingTwo-Digit Addition with RegroupingAddition Within 100Repeated Addition as MultiplicationMultiplication Facts Within 100Division as Equal SharingDivision as Grouping (Measurement Division)Division: Grouping (Repeated Subtraction) ModelDivision: Fair Sharing ModelDivision as Equal SharingDivision as GroupingBasic Division FactsDivision Facts Within 100Two-Digit by One-Digit DivisionDivision with RemaindersRemainders and Quotients in DivisionDivision Word ProblemsIntroduction to Long DivisionFactors and MultiplesPrime and Composite NumbersEquivalent FractionsRelating Fractions and DecimalsDecimal Place ValueReading and Writing DecimalsComparing and Ordering DecimalsAdding and Subtracting DecimalsMultiplying DecimalsDividing DecimalsDividing FractionsMixed Number ArithmeticOrder of OperationsOperators and ExpressionsArithmetic Operators and Operator PrecedenceComparison Operators and Boolean TestsLogical Operators and Boolean AlgebraBoolean Algebra and Fundamental LawsCombinational Circuit DesignFlip-Flops and LatchesBinary Counters: Design and AnalysisBinary ArithmeticFixed-Point Number RepresentationTwo's Complement RepresentationOverflow and Underflow DetectionBinary Adders: Half-Adders and Full-AddersFull Adder and Carry PropagationCarry Lookahead Adder DesignHalf Adder Circuit DesignMultiplication Circuit DesignSequential Circuit DesignRegisters and Register FilesInstruction Set Architecture (ISA)Kernel Architecture and OS StructureSystem Calls and User/Kernel ModeProcesses and the Process Control BlockProcess Creation: fork() and exec()Process Termination and Resource CleanupProcess States and State TransitionsThreads and ConcurrencyThe Critical Section Problem and Race ConditionsCritical Section Problem: Formal DefinitionSoftware-Only Mutual Exclusion Solutions

Longest path: 70 steps · 246 total prerequisite topics

Prerequisites (1)

Leads To (1)