Skip to content
BytePatterns

Designing Thread-Safe Code

Concurrency: lesson 10 of 10

Don't share, freeze it, or guard it.

Lesson 10 of 10 · 5 min

Designing Thread-Safe Code

Step 1 of 9

Work down the list in order: don't share it, freeze it, or guard it.

The Idea

Work down the list. Give each thread its own state; make whatever must be shared immutable; guard the small remainder with one lock whose scope is written down. Reach for clever lock-free tricks only after the first three have genuinely failed.

Real-World Example

A museum conservation studio. Each conservator has a private bench for the object in their care, the reference photographs on the wall are read-only prints anyone may consult, and the single vacuum table has a booking sheet by the door.

The Code

import threading
readings = [3, 8, 1, 9, 4, 7]     # shared, but never mutated
totals = {}
lock = threading.Lock()           # guards: totals, and nothing else

def sum_chunk(name, chunk):
    subtotal = sum(chunk)         # thread-local work, no lock needed
    with lock:
        totals[name] = subtotal

parts = {"left": readings[:3], "right": readings[3:]}   # private slices
ts = [threading.Thread(target=sum_chunk, args=kv) for kv in parts.items()]
for t in ts: t.start()
for t in ts: t.join()
print(sorted(totals.items()), sum(totals.values()))

Your turn

Put the steps in the right order.

  1. Guard whatever genuinely remains with one documented lock
  2. List every piece of state that two threads can reach
  3. Give each thread its own copy of what it alone writes
  4. Freeze the shared data that never changes after creation

Mini quiz

1 / 3

The safest option for mutable state is: