When two threads try to update the same variable at the same time, you get **Race Conditions** and corrupted data. You must protect your shared state using Synchronization Primitives.
The simplest way. Only one thread can enter the code block at a time. **Pros:** Safe. **Cons:** It blocks threads entirely. You cannot `await` inside a `lock` block. For async code, use **SemaphoreSlim** instead.
The ultimate performance tool. `Interlocked.Increment(ref count)` updates a variable at the CPU hardware level without a lock. It is hundreds of times faster than a `lock` or `Semaphore`. Use it for counters and simple state flags.
Never use a `Dictionary` in a multi-threaded app; use **ConcurrentDictionary**. It is internally partitioned so that multiple threads can write to different 'buckets' of the dictionary without blocking each other. This is the foundation of high-performance caches.
Q: "What is a 'Deadlock' and how do you avoid it?"
Architect Answer: "A deadlock happens when Thread A is waiting for a Resource held by Thread B, while Thread B is waiting for a Resource held by Thread A. They both freeze forever. We avoid this by: 1) Always acquiring locks in the same order. 2) Using **Timeouts** (`WaitAsync(timeout)`). 3) Avoiding `.Result` or `.Wait()` on async tasks, which is the most common cause of deadlocks in ASP.NET applications."