Where concurrent code goes wrong
- Race conditionsRace conditionsThe result depends on the order in which threads happen to run.Opens in a new tab occur when the outcome of a computation depends on the non-deterministic order or timing of the execution of multiple threads accessing shared data.
- DeadlocksDeadlocksTwo or more threads wait on each other forever.Opens in a new tab occur when two or more threads are blocked indefinitely, each waiting for a resource held by another thread in the group.
- LivelocksLivelock and starvationThreads that keep running without progress, and threads that never get a turn.Opens in a new tab occur when threads are actively trying to respond to each other, but keep reacting without making progress.
A common cause: sharing one object
A frequent way to get a race condition is to share one mutable object, such as a rendering engine, between parallel workers when it isn’t thread-safe. Typical symptoms are exceptions about duplicate keys or concurrent operations, and corrupted output. The fix is not to share it. Create a separate instance for each worker. A worked example is in fan-out and fan-in with Parallel.ForFan-out and fan-in with Parallel.ForRender independent items on all cores, keep the results in order, then merge them one at a time.Opens in a new tab.
The tools for preventing the first two are in the synchronization noteSynchronization primitives and concurrent collectionsWhat to use when several threads touch the same data.Opens in a new tab. The deadlock from blocking on async code is in deadlocksDeadlocksTwo or more threads wait on each other forever.Opens in a new tab.