# Answer - Theoretical Questions

## 1.What are atomic variable?

Atomic variables are variables that support lock-free, thread-safe operations on single variables. 
They ensure that read-modify-write operations (like increment, compare-and-set) are performed atomically without interruption.

**Difference from ordinary variables: ** ordinary variables are not thread safe ; concurrent access can race conditions.
Atomic variables provide built-in thread safety without explicit synchronization.

## 2.Four classes from java.util.concurrent.atomic

- 'AtomicInteger'
- 'AtomicLong'
- 'AtomicBoolean'
- 'AtomicReference'

**Use case for AtomicInteger:** A request counter in a web server that is incremented concurrently by multiple threads. 
AtomicInteger ensures the count never misses an increment.

## 3.Compare locks with atomic variables 

| Scenario                                        | Better Choice |
|-------------------------------------------------|----------------|
| Simple counter or single variable update        | Atomic variable (lower overhead) |
| Multiple related variables (like bank transfer) | Lock (to ensure multi-step atomicity) |

**Conclusion:** Use atomics for simple state, locks for compound actions.

## 4. A program free of race conditions but poor under high contention

This happens due to **scalability limitations** even when correctness is guaranteed. Possible factors:

1. **Lock contention** – Threads spend time waiting for locks instead of doing work.
2. **Context switching overhead** – Frequent thread switching wastes CPU cycles.
3. **Cache coherence traffic** – Cores invalidate and refresh cache lines repeatedly.

## 5. Why adding more threads does not always improve performance

- **Context switching** – Saving/restoring thread state has cost.
- **Contention** – Threads compete for shared resources.
- **Cache coherence** – Multiple cores must synchronize caches.
- **Synchronization overhead** – Locks and barriers slow execution.

Adding more threads beyond CPU core count typically increases overhead without benefit.

## 6. Why deadlocks appear in production, not testing

**From thread-scheduling perspective:** Testing environments have predictable scheduling,
low load, and short runtimes. Production has unpredictable interleaving, high concurrency, and longer execution windows.

**Two strategies to expose deadlocks during testing:**
1. Run tests thousands of times with randomized thread interleavings.
2. Use tools or `Thread.sleep` at random points to force rare scheduling patterns.

