Thread safety keeps shared data and operations correct when multiple threads access or modify them concurrently. Problems arise when updates interleave, reads observe modifications, or timing changes operation order. section 7.4 section 13.3
Apply these safeguards when coordinating shared state:
- Use one lock for the entire logical operation, while keeping its duration as short as practical. section 7.4
- Acquire multiple locks in a consistent order, avoid calling uncontrolled code while locked, and expect overly short locks to permit races. section 7.7
- Prefer lock for ordinary synchronization; reserve Interlocked for measured bottlenecks and use it consistently for every access to the protected variable. section 4.5
- Use immutable collections when practical: modifications return new collections, while internal structures can share data to reduce copying. section 13.3
Two operands, one logical update
Reading two operands under separate locks and then adding them can observe a partial update. Protecting the complete operation with an appropriate locking strategy avoids composing individually safe operations into an unsafe result. section 7.4
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;
}
}
Demonstrates separate locks around operand reads and writes, making the boundary between individually protected accesses and a complete thread-safe operation concrete. section 7.4







