Skip to content

Locks (Lock vs RLock)

A Lock allows only one thread to enter a critical section at a time.

lock_example.py
import threading
 
lock = threading.Lock()
count = 0
 
 
def add():
    global count
    for _ in range(100_000):
        with lock:
            count += 1
 
 
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=add)
 
t1.start(); t2.start()
t1.join(); t2.join()
 
print(count)

A piece of code that must not be interrupted by another thread while it updates shared data.

An RLock can be acquired multiple times by the same thread.

Use it when:

  • a function that holds a lock calls another function that tries to acquire the same lock
rlock_example.py
import threading
 
lock = threading.RLock()
 
 
def outer():
    with lock:
        inner()
 
 
def inner():
    with lock:
        print("safe")
 
 
t = threading.Thread(target=outer)
t.start(); t.join()
sketch A Lock will deadlock against itself; an RLock will not p5.js
One thread, one lock, acquired twice. A plain Lock has no idea who holds it -- the second acquire blocks forever against a lock the SAME thread is holding, which is a deadlock with only one thread involved. An RLock records its owner and a count, so the owner may re-enter. Measured: the second acquire returns False on a Lock and True on an RLock. The catch is the release count -- an RLock stays held until you release it as many times as you took it.
  • Keep with lock: blocks short.
  • Always acquire locks in a consistent order if using multiple locks.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading