A Lock protects shared data so only one thread updates it at a time. Replay shows the two worker threads taking turns in one source pane.

Counter Updates

shared_counter_lock.py
import threading


counter = {"value": 0}
lock = threading.Lock()


def add(delta, repeats):
    for _ in range(repeats):
        with lock:
            counter["value"] = counter["value"] + delta
            print("value=" + str(counter["value"]))


repeats = 

small = threading.Thread(target=add, args=(1, repeats))
large = threading.Thread(target=add, args=(10, repeats))

small.start()
large.start()
small.join()
large.join()

print("final=" + str(counter["value"]))
import threading


counter = {"value": 0}
lock = threading.Lock()


def add(delta, repeats):
    for _ in range(repeats):
        with lock:
            counter["value"] = counter["value"] + delta
            print("value=" + str(counter["value"]))


repeats = 

small = threading.Thread(target=add, args=(1, repeats))
large = threading.Thread(target=add, args=(10, repeats))

small.start()
large.start()
small.join()
large.join()

print("final=" + str(counter["value"]))
import threading


counter = {"value": 0}
lock = threading.Lock()


def add(delta, repeats):
    for _ in range(repeats):
        with lock:
            counter["value"] = counter["value"] + delta
            print("value=" + str(counter["value"]))


repeats = 

small = threading.Thread(target=add, args=(1, repeats))
large = threading.Thread(target=add, args=(10, repeats))

small.start()
large.start()
small.join()
large.join()

print("final=" + str(counter["value"]))
lock-protected mutation Use a lock around a read-modify-write operation when multiple threads share the same object.