Command Palette

Search for a command to run...

Hectal
Back to the lesson: Topic 12.3 — Threads with threading
Python · Example 2 of 3

A race condition, replayed by hand

Each generator is a thread's three steps. We choose the order in which they run, so the bug happens every time.

A thread is a flow of code that runs inside your process and shares its memory. You start threads with threading.Thread, wait for them with join, and protect shared data with a Lock; queues and thread-local data are the safer ways to share and separate state.

Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.

Ready for more? This phase has 6 hands-on exercises with automatic checks.

Practice questions

Write the code in the editor, run it, then open the model answer to compare.

01

A shared counter starts at 0 and many threads add to it. Write a function work(times) that adds 1 to the global counter times times, with each addition inside with lock: so no update is lost. Call work(5) once and print counter.

02

Write a function try_take(lock) that returns "got it" if the lock could be acquired without waiting (and releases it), and "busy" otherwise. Test it on a free lock and a held lock.

03

Write a function drain(q) that takes every item out of a queue.Queue without blocking and returns them as a list.

Explain it without notes

01

What is a race condition? Give an example with a counter.

02

How does a Lock prevent a race, and why use with lock: instead of acquire/release?

03

What is a deadlock, and how do you prevent one?

04

Why is queue.Queue usually better than shared variables with locks?

05

Your script prints its last line but the process never exits, and it uses threads. What is the likely cause, and what do you change?

A race condition, replayed by hand
Sign in to run this example in your browser.

Expected output

A read 100
B read 100
A calculated 70
B calculated 50
A wrote 70
B wrote 50
Final balance: 50 (it should be 20)