Programming Fundamentals › Concurrency & Async
Critical Section
Code that must not run concurrently with itself.
Also known as: critical region
A critical section is a piece of code that touches shared state and must not run in two threads at the same time. Two threads running inside it can read and write the same data in an order that gives wrong results. Protecting the section means letting only one thread inside at a time.
The usual way is a mutex around the code:
import threading
lock = threading.Lock()
counter = 0
def add_one():
global counter
with lock: # the critical section: read and write as one unit
value = counter
counter = value + 1
Two things decide whether a section is critical. It must touch state that other threads can reach, and at least one of those accesses must write. Code that works only on its own local variables doesn’t need a lock.
The trade-off is that a critical section serializes the work inside it. Keep it short. Doing slow I/O, network calls or heavy computation while holding the lock makes every other thread wait, which can erase the benefit of having threads at all.
The classic mistake is drawing the boundary too narrowly, locking one line of a multi-step update, so the other steps can still interleave. The opposite mistake is drawing it too widely and holding the lock across I/O. Lock the whole update that must stay consistent, and nothing else. Check-then-act races show what happens when the boundary is wrong.