Deadlocks in Windows: how to spot them and how to avoid them

The game freezes for two seconds in the middle of a duel. FPS reads 240 and the picture stands still. The server drops a tick even though the CPU is idling. Behind some of these cases sits a deadlock, a thread lock-up. This article shows how to recognise them and how to get rid of them.
What a deadlock is
Deadlock from Valve… we write about it a lot - unfortunately this time we mean something less colourful - a system deadlock. It happens when two threads wait on each other for resources they have already locked. Thread A holds lock 1 and waits for lock 2. Thread B holds lock 2 and waits for lock 1. Neither gives way, so both stand still until the process dies.
From the player perspective there is no load to see. The CPU has headroom, the GPU has headroom, and still nothing moves.
Where it hurts in games and on servers
| Area | Example in games | Consequences |
|---|---|---|
| Client | A lock on the render thread while a frame waits for network data | A stutter or a black screen at high FPS |
| Server | Game logic waits for a result from another thread, for example from AI | Delays in state synchronisation, a drop in tick-rate |
| Matchmaking | The player matching algorithm waits for data locked by another process | Longer queues, more timeouts when a map is assigned |
We connect to your PC remotely, save a restore point, then work down through BIOS, power, drivers and input. The same benchmark at the end shows how much of it landed. For six months after the session we stay with you on Discord.
How to detect deadlocks in Windows
- Task Manager, Details tab. Right-click the process and select Analyze wait chain. The window shows what the selected process is waiting on.
- Process Explorer (Sysinternals). W
Open Handleslook for the names of mutexes, files and COM objects held too long. - PerfMon. Counters
Thread StateandThread Wait Reason, that is, the thread state and the reason it is waiting. A value of 5 in Thread State means waiting. - Process dump and WinDbg. Save a dump of the hung process and go through the stacks with the command
~* k. Deadlocked threads sit on the sameWaitForSingleObjectfor the whole dump.
Where they come from
- A different lock ordering in different threads
- An I/O operation performed inside a critical section
- Mixing COM apartments, that is, synchronous calls between STA and MTA
- Priority inversion, when a low priority thread holds a lock a high priority thread needs
How to avoid them
| Strategy | What to do | Example code (C++/Win32) |
|---|---|---|
| Lock ordering | Settle on one lock ordering and stick to it across the whole codebase, for example alphabetically by name. | void AcquireAll(std::vector<MutexHandle>& locks){ std::sort(locks.begin(), locks.end(), [](auto& a, auto& b){ return a.name < b.name; }); for(auto& l : locks) WaitForSingleObject(l.handle, INFINITE); } |
| Try-lock with a timeout | If you do not get the lock within the given time, release what you already hold and start again. | bool TryLock(MutexHandle& m){ return WaitForSingleObject(m.handle, 500) == WAIT_OBJECT_0; } |
| Do not block the main thread | Keep the UI and render threads free. Do I/O asynchronously. | // asynchronous read via an overlapped structure ReadFile(hFile, buf, size, NULL, &ov); // no blocking calls in the critical section |
| SRWLOCK instead of a mutex | Many readers work in parallel, and only writes get exclusivity. | SRWLOCK lock = SRWLOCK_INIT; AcquireSRWLockShared(&lock); ReleaseSRWLockShared(&lock); |
| COM apartment hygiene | UI in STA, server logic in MTA. Avoid synchronous calls between them. | CoInitializeEx(NULL, COINIT_MULTITHREADED); |
| A watchdog that detects cycles | Check the wait graph every few seconds. A cycle means a deadlock, so restart the thread or the application. | Depth-first search (DFS) over the wait-for graph |
Concrete cases from game servers
| Problem | Solution |
|---|---|
| Matchmaking waits on the database (SQL Server) | Shorten transactions, review query plans, enable READ COMMITTED SNAPSHOT. |
| The AI thread holds a mutex for the whole computation | Move the computation outside the critical section and release the lock right after writing the result. |
| Game state synchronisation at a high server tick-rate | Use SpinLock instead of Mutex, but keep the critical section within a few microseconds. |
What the player gets out of it
- Shorter delays. Removing a deadlock takes the milliseconds you will not see in any benchmark off the server response time.
- A stable session. The client stops freezing at random moments, and the FPS graph stops having holes in it.
- Better scalability. The server handles more players on the same hardware.
Checklist after rolling out the changes
- Task Manager. Under heavy load no process waits forever. Check it with the Analyze wait chain.
- PerfMon.
Thread Stateof the game threads does not stay at 5 (Wait) for the whole measurement. - Server. Average server tick-rate matching its configured value, with no dropped ticks.
- Profiler. Intel VTune or AMD uProf shows no long critical sections.
So what you need?
A deadlock consumes no resources, so you will not see it on any load graph. Look for it where the threads stand still: in Task Manager, in Process Explorer and in stack dumps.
Three habits are enough to stop producing them. Settle on one lock ordering. Keep I/O out of critical sections. On the server reach for lock-free structures, and on the client for asynchronous I/O. You see the result in the ping, in frame stability and in the number of players the server holds without choking.
Related articles
- Windows gaming optimisation
- Valorant: too much FPS breaks the client tickrate
- 10 Best Ways to Improve FPS in games for 2026
- The official list of useful gaming tools
Frames dropping exactly when the fight starts?
That drop lands in the one second that decides the round, and no graphics preset fixes it. We tune your PC remotely: Windows, drivers, BIOS and network. You measure it yourself, in your own game, before and after, with us watching.
See PC optimization →Six months of support after the session. Not sure it is worth it? Ask for a free check on our Discord first.Our free tools
Built in house. No account, no limits.
Ultimate Demo AnalyzerUpload a CS2 demo and get your mistakes and round stats written out.
Free, no account
Deadlock Replay AnalyzerThe same for Deadlock: a replay breakdown and a plan for the next matches.
Free, no account
Sensitivity ConverterCarry your cm/360 between games without losing muscle memory.
Free, no account
Aim TrainerThirty seconds, three levels. No install, no account.
Free, no account





