When two threads each wait for a lock the other holds, both stop forever.
Why Thread A holds lock 1 and waits for lock 2, while B holds lock 2 and waits for lock 1 → Effect Both stop forever, and related threads stop one after another → On screen The whole server stops, and everyone disconnects when the watchdog restarts it
Set lock ordering rules, use locks with timeouts, add a watchdog that captures a thread dump at the moment of the hang.
On the graph
Mass disconnect · Connection count, server outbound traffic
Where to look
Call stacks of every thread captured during the hang: jstack for the JVM (finds and flags deadlocks automatically), dotnet-stack for .NET, gdb’s thread apply all bt for native servers, or dump a core file with gcore, restart, and analyze it afterward
Confirmed if
Two or more threads are stuck with stacks waiting for locks held by each other, and process CPU utilization is near 0 the whole time
Ruled out if
One thread spinning at 100% CPU during the hang: infinite loop. Threads waiting on DB or external responses: points to blocking calls or thread pool exhaustion
Check with
Infra tools (no game code needed)
Sources
Runtime locking correctness validatorLinux kernel Taking two locks in opposite orders causes circular waiting and a deadlock (lock inversion deadlock); the Linux kernel checks lock ordering and warns in advance
Liveness, Readiness, and Startup ProbesKubernetes A liveness probe catches a deadlock, where the app is running but can’t make progress, and restarts the container