## 🧠 Theoretical Questions

### ⚛️ Atomic Variables & Synchronization

---

**1 -** What are atomic variables?

Explain their purpose and how they differ from ordinary (non-atomic) variables.

Atomic variables are variables that support thread-safe operations that are performed atomically, meaning the operation cannot be interrupted in the middle.

Their purpose is to avoid race conditions when multiple threads read and update the same value at the same time. For example, an operation like count++ is not atomic for a normal int variable because it involves reading the value, increasing it, and writing it back.

Atomic variables, such as AtomicInteger, provide methods like incrementAndGet() that perform the whole update safely as one atomic operation.

The main difference from ordinary variables is that ordinary variables are not thread-safe under concurrent updates, while atomic variables are designed to be safely used by multiple threads without using explicit locks for simple operations.


**2 -** Name at least four classes from the `java.util.concurrent.atomic` package that provide atomic operations for different data types.

For one of them, briefly describe a typical use case.

Some classes from the java.util.concurrent.atomic package are:

1. AtomicInteger
2. AtomicLong
3. AtomicBoolean
4. AtomicReference

A typical use case for AtomicInteger is a thread-safe counter. For example, in a server application, multiple threads may handle requests at the same time and increment a shared request counter. Using AtomicInteger.incrementAndGet() ensures that no updates are lost.


**3 -** Compare locks with atomic variables.

In which scenarios is using a lock a better choice than an atomic variable, and vice versa?

Locks and atomic variables are both used to make concurrent code thread-safe, but they are useful in different situations.

Atomic variables are usually better for simple operations on a single value, such as incrementing a counter, setting a boolean flag, or updating a reference. They are often faster and do not require explicit locking.

Locks are better when an operation involves multiple steps, multiple variables, or multiple objects that must be updated together. For example, transferring money between two bank accounts should use locks because both accounts must be protected and the whole transfer must be atomic.

In short, atomic variables are a good choice for simple independent updates, while locks are a better choice for complex critical sections that need to protect several related operations.
