Several threads run counter += 1 on a shared global, 1M times each. Is the final count guaranteed correct with the GIL?
Options
- Yes, the GIL makes
counter += 1a single atomic step - No,
+=is several steps, and threads can interleave between them (Correct option) - Yes, but only on Linux, where the GIL is stricter
- No, Python forbids sharing a global between threads
Answer
No, += is a read-modify-write of several bytecodes and threads can interleave
Why
The GIL protects Python's internals, not your logic. counter += 1 is several small steps: read counter, add 1, write it back.
A thread can be paused between the read and the write. Meanwhile another thread updates the counter, and then the first thread writes an old value: one update is lost. This is a race condition.
Protect shared data with a Lock.
lock = threading.Lock()
def work():
global counter
for _ in range(1_000_000):
with lock:
counter += 1Remember
The GIL is not thread safety. Use a Lock for shared data.