ProgrammingBackend Developer

What is a 'volatile' variable in Java and how does it differ from 'synchronized'? When and for what purpose should volatile be used?

Pass interviews with Hintsage AI assistant

Answer

volatile is a variable modifier that ensures visibility of changes to this variable by all threads. If a variable is declared as volatile, its reading and writing occur directly from the main memory, bypassing the local cache of threads. This prevents caching of values locally within the thread.

synchronized is a keyword that provides not only visibility but also mutual exclusion: only one thread can execute a synchronized block at a time for a single object.

You should use volatile variables for simple flags and counters when:

  • the value of the variable does not depend on its previous state (for example, a counter is written only once and read multiple times);
  • there is no need for a more complex sequence of operations (check-then-act).

Example of using volatile:

class Flag { private volatile boolean running = true; public void stop() { running = false; } public void loop() { while (running) { // ... } } }

Trick Question

Can volatile be used to ensure the atomicity of incrementing a variable?

Answer: No, volatile does not ensure the atomicity of operations. For example, counter++ is not atomic even if counter is declared as volatile because the operation involves reading, modifying, and writing (multiple actions) that can be interrupted by another thread. Atomicity is ensured using synchronized or classes from the java.util.concurrent.atomic package.

Example:

class Counter { private volatile int count = 0; public void increment() { count++; // NOT an atomic operation! } }

Examples of real errors due to ignorance of the nuances of the topic


Story

In an online store project, the thread completion flag for order processing was implemented without volatile. As a result, one of the threads "stuck" in an infinite loop, as it did not see the variable change made from another thread. Diagnosis took several days.


Story

In a financial system, a developer used volatile int for a transaction counter. Under peak loads, the number of transactions began to "disappear." The reason was the loss of atomicity during complex increment operations.


Story

Developers confused volatile and synchronized, trying to use volatile to ensure mutual exclusion access to critical sections, which led to data races and elusive bugs in a multithreaded application.