a critical section
A critical section is a piece of code that touches shared mutable state, and so must not be run by two threads at the same time. Think of a single-occupancy phone booth with a door: while you are inside making your call, nobody else may enter; they wait outside until you leave. The booth is the critical section, and the rule 'one person at a time' is exactly what keeps the shared resource from being scrambled. Identifying which stretches of your code are critical sections is the first practical step in making a concurrent program correct.
More precisely: a critical section is the span of code, from the first instruction that reads or writes some shared data to the last one that does, during which the shared data may be in an inconsistent, half-updated state. While a thread is in the middle of such a section - say it has read a value, computed a new one, but not yet stored it back - the data is temporarily wrong, and another thread that barges in will see or stomp on that mess. The job, then, is to ensure that at most one thread is inside the critical section at a time, so each thread completes the whole update before the next begins. This guarantee is called mutual exclusion, and the tools that provide it (mutexes, and friends) are the subject of Field n.
Why naming critical sections helps you think: it focuses the whole problem. You do not need to make your entire program thread-safe; you need to find the specific regions that touch shared state and protect just those. Keep critical sections small - hold the protection for the briefest stretch that still covers the whole inconsistent window - because a thread inside a critical section blocks others, so a needlessly large one throttles your concurrency. And make sure every access to a given piece of shared data is covered: a critical section that protects the write but leaves a read unguarded still races on that read.
The three steps of counter++ - read counter, add one, write it back - form a critical section. Wrapping them so only one thread runs them at a time (for example, between pthread_mutex_lock() and pthread_mutex_unlock()) makes the whole update happen as one indivisible step.
A critical section is the code that must run with mutual exclusion - one thread at a time.
Protecting one critical section but forgetting another that touches the same data still leaves a race - every access to a given shared item must use the same protection. And keep the section small: an oversized critical section serializes work that could have run in parallel.