liveBook · Manning

Race condition

As explained in C# Concurrency: Asynchronous and multithreaded programming

A race condition is a concurrent-execution defect in which program results depend on uncontrollable timing or interleaving between execution flows.

A race condition occurs when concurrent execution produces different results because uncontrollable timing determines how operations interleave. Even deadlock-free code can read mixed or outdated shared state when a multi-step operation releases its locks between steps. section 7.4 section 7.0

Listing 7.12 Holding just one lock at a time
public int Add()
{ 
   int leftCopy,rightCopy;
   lock(_leftOperandLock)
   {
       leftCopy = _leftOperand;
   }
   lock(_rightOperandLock)
   { 
      rightCopy = _rightOperand;
   }
   return rightCopy + leftCopy;   
}

public int SetOperands(int left, int right)
{ 
   lock(_leftOperandLock)
   {
       _leftOperand = left;
   }
   lock(_rightOperandLock)
   { 
      _rightOperand = right;
   }
}

Compare the separate locks in Add and SetOperands: each protects one access, but neither protects the complete operation, allowing their steps to interleave. section 7.4

Reduce race conditions by applying synchronization at the operation boundary:

  • Protect shared data with locks and hold them for the entire operation, while keeping the locked duration as short as practical. section 7.7
  • Acquire multiple locks in a consistent lock hierarchy; avoiding multiple simultaneous locks does not automatically make compound operations safe. section 7.7 section 7.3
  • Release locks before calling code outside your control, including event handlers, because callbacks can create additional synchronization cycles. section 7.7 section 7.3

How C# Concurrency: Asynchronous and multithreaded programming covers it

How deep it goes
Explains timing-dependent interleavings through C# lock examples, but stops short of memory-model internals or quantitative performance analysis.
Examples
Demonstrates separate-lock Add and SetOperands methods whose operations interleave, producing correct, stale, or inconsistent operand results.
What it assumes
Assumes familiarity with multithreaded execution and C# locks while contrasting concurrent behavior with single-threaded sequencing.
What you can do after
Diagnose timing-dependent shared-state defects and apply lock scope, lock hierarchy, and callback-safety rules.
How it connects
Connects race conditions with concurrency, shared data, locks, deadlocks, synchronization, and thread scheduling.

Also explained in

Compare how 20 books explain race condition →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of C# Concurrency: Asynchronous and multithreaded programming. The section links point to the parts of the book it draws on.