Deadlocks with application locks

Concurrency in Python services Mid-level Python 3.13+ PostgreSQL 17+ Reviewed By Best Latest Apps

Pick the fix

transfer(a, b) locks a then b; transfer(b, a) locks b then a. Fix?

Options
Hint 1 of 1

What would stop the cycle forming?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Lock both accounts in sorted id order in every path

Correct. Same order everywhere means no cycle.

A deadlock needs a cycle: each thread holds one lock and waits for the other's. If every path takes locks in the same global order, such as by account id, no cycle can form.

Why not the others?
  • B Add a sleep between the two acquisitions. Changes timing, not the cycle.
  • C Use more threads. More contenders, same cycle.
  • D Catch exceptions around the second acquire. A blocked acquire raises nothing.

30-second answer

Path one takes lock A then waits for B; path two holds B and waits for A. Neither can proceed: a deadlock. Prevent it by always acquiring locks in one global order (for example by sorted resource id), holding as few locks as possible for as short as possible, and using timeouts on acquisition so a stuck path fails loudly instead of hanging. In databases the engine detects cycles; in application code nothing does.

Practise saying it · 30 s. No recording, just a timer

Prevent deadlocks in code.

Say your answer out loud, then check which of these points you covered:

  • Lock cycle
  • Global lock order
  • Short critical sections
  • Acquire timeouts
  • No I/O under locks

Deep dive

lock.acquire(timeout=1) returns False instead of hanging.

Never call out to I/O or other services while holding a lock.

asyncio locks deadlock the same way across coroutines.

A thread dump (py-spy dump) shows who holds what.

Common mistakes

  • Inconsistent lock order across code paths.
  • Holding a lock while awaiting a network call.
  • Re-acquiring a non-reentrant Lock in the same thread.

Senior take & follow-ups

Name the cycle, then global ordering, short critical sections and acquisition timeouts.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you diagnose a hung process?

    Show hint

    py-spy dump or faulthandler to see each thread's stack.

  2. RLock or Lock?

    Show hint

    RLock allows the same thread to re-acquire; it hides design problems but avoids self-deadlock.

Suggest a fix if something here is wrong or out of date.