DeadlocksWhat is Deadlock?Hard⏱️ ~2 min

Debugging Deadlocks

Practical Guide
When deadlock occurs in production, you need to identify the cycle, find the root cause, and fix the ordering or design.

Step 1: Get a Thread Dump

Java: jstack <pid> or send SIGQUIT. Go: Send SIGQUIT or use pprof. Python: faulthandler module. The dump shows every thread, its state, and what lock it waits for.

Step 2: Find Blocked Threads

Look for threads in BLOCKED state. Each blocked thread shows which lock it wants and who holds it. Trace the chain: A waits for B, B waits for C, C waits for A. That is your cycle.

Step 3: Identify the Code Paths

Stack traces show where each thread acquired its locks and where it is waiting. Two threads holding locks in opposite order? That is your bug. Find where the ordering diverges.

Thread Dump Analysis
Thread-1 BLOCKEDwaiting on lock@0x123owned by Thread-2at Transfer.execute()Thread-2 BLOCKEDwaiting on lock@0x456owned by Thread-1at Transfer.execute()

Prevention for Next Time

Lock ordering: Document and enforce a global order for all locks. Timeout: Use tryLock with timeout, log and retry on failure. Testing: Stress test concurrent code paths. Static analysis: Tools can detect potential lock order inversions.

Pro Tip: Java jstack automatically detects and reports deadlock cycles. Look for "Found one Java-level deadlock" in the output. It does the cycle detection for you.
💡 Key Takeaways
Thread dump is the primary diagnostic. Shows all threads, their states, locks held and wanted.
Find BLOCKED threads, trace the wait-for chain, identify the cycle. That is the deadlock.
Stack traces reveal where locks were acquired. Find the code paths with opposite ordering.
Prevention: enforce lock ordering, use tryLock with timeout, stress test concurrent paths.
Java jstack automatically detects deadlocks. Other platforms need manual analysis.
📌 Examples
1jstack output: Thread-1 blocked on 0x123 (owned by Thread-2), Thread-2 blocked on 0x456 (owned by Thread-1).
2Fix: both code paths must acquire lockA before lockB. Refactor the one that does B→A.
3tryLock pattern: if (!lock.tryLock(100, MILLISECONDS)) { log.warn(); retry later; }
← Back to What is Deadlock? Overview