Whenever two processes/threads are reading and writing the same variables in a language with SharedStateConcurrency, it is possible that one process will interfere with the other -- a RaceCondition.
For example, suppose that both processes are trying to increment the same variable. They both have the line
x := x + 1in them. One way for each process to execute this statement is for it to read the variable, then add one to the value, then write it back. Suppose the value of x was 3. If both processes read x at the same time, they would get the same value 3. If they then both added 1 to it, they would both have the value 4. They would then both write 4 back to x. The result is that both processes incremented x, but its value is only 4, instead of 5.
For these processes to execute properly, they must ensure that only one of them is executing the statement at a time. A set of statements that can have only one process executing it at a time is a critical section. Another way of saying this is that processes need mutually exclusive access to the critical section.
There are several ways to implement a critical section. If you have a single processor running all the processes that might enter the critical section, you can DisableInterrupts? while a process is in the critical section. If you have multiple processors and the critical section doesn't take long to execute, you should use BusyWaiting. If the critical section is long or if you might have interrupts during the critical section then you should use SemaphoresForMutualExclusion. If you are very clever then you might be able to think up an AlternativeToCriticalSection?.
Critical sections are very easy to spot in many FunctionalProgrammingLanguages, because these tend to tag explicitly non-pure state changes which are almost always critical sections.