Thread Synchronization with Lock
The problem: race conditions
A race condition happens when two threads update shared state at the same time.
Example: incrementing a shared counter.
race_condition.py
import threading
counter = 0
def inc():
global counter
for _ in range(100_000):
counter += 1
t1 = threading.Thread(target=inc)
t2 = threading.Thread(target=inc)
t1.start(); t2.start()
t1.join(); t2.join()
print("counter:", counter)race_condition.py
import threading
counter = 0
def inc():
global counter
for _ in range(100_000):
counter += 1
t1 = threading.Thread(target=inc)
t2 = threading.Thread(target=inc)
t1.start(); t2.start()
t1.join(); t2.join()
print("counter:", counter)You might expect 200000, but results can vary.
Fix with Lock
lock_fix.py
import threading
counter = 0
lock = threading.Lock()
def inc():
global counter
for _ in range(100_000):
with lock:
counter += 1
t1 = threading.Thread(target=inc)
t2 = threading.Thread(target=inc)
t1.start(); t2.start()
t1.join(); t2.join()
print("counter:", counter)lock_fix.py
import threading
counter = 0
lock = threading.Lock()
def inc():
global counter
for _ in range(100_000):
with lock:
counter += 1
t1 = threading.Thread(target=inc)
t2 = threading.Thread(target=inc)
t1.start(); t2.start()
t1.join(); t2.join()
print("counter:", counter)Best practices
- Keep locked sections small.
- Prefer
with lock:with lock:so you donβt forget to release. - Avoid deadlocks (donβt acquire multiple locks in random order).
π§ͺ Try It Yourself
Exercise 1 β Basic Lock Usage
Exercise 2 β Lock as Context Manager
Exercise 3 β Detect Locked State
If this helped you, consider buying me a coffee β
Buy me a coffeeWas this page helpful?
Let us know how we did
