A race condition is when multiple threads/processes/clients all use a resource, without proper use of locks.
A race condition is when multiple threads/processes/clients all use a resource, without the proper use of locks.
In multi-threaded programs, race conditions occur because context switches between threads are often erratic and unpredictable, often causing a shared value to change at inopportune times.
Servers are also vulnerable to race conditions, sometimes more so, because there are many independent clients which act independently, as well as delays caused by network communication.
Consider the example of two people simultaneously editing the same document:
- Person #1 sees an incorrect line. #1 begins to fix this line, but is a slow typist.
- Person #2 sees the same mistake - while #1 is typing - and fixes it.
- #1 and #2 commit their edited documents at the same time, without the other being notified.
- #1's change reaches the server first, and the server writes it to disk.
- #2's change reaches the server later, and the server silently overwrites #1's change.
Locks are a common way to avoid race conditions. Consider the above example with proper locking:
- Person #1 sees the incorrect line and starts editing it.
- Person #2 also sees the incorrect line, but is unable to edit until Person #1 has pushed their changes to the server.
- Person #1's changes are seen by both #1 and #2.
- Person #2 decides that #1's changes are adequate, and decides not to edit.
In this scenario, edit access to the document is restricted to one client only. This prevents Person #2 from silently overwriting Person #1's changes. See Wikipedia for further examples.