When concurrently executing processes communicate among themselves or use shared resources, they can obviously influence each other. This influence can lead to errors that only exhibit themselves in certain scenarios of concurrent execution. Such errors are called race conditions.
Bernstein conditions from 1966 state that given sets of inputs and sets of outputs for concurrently executing processes, race conditions can only occur when either sets of outputs of two processes overlap, or a set of inputs of a process overlaps with a set of outputs of other processes.
Race conditions are notoriously difficult to discover. Process synchronization provides means of avoiding race conditions by controlling or limiting the concurrency when executing code where race conditions can occur. This code is typically denoted as critical sections.