Java Interview Questions
Java
Web DevelopmentBackendQuestion 23
What is the 'volatile' keyword in Java?
Answer:
The volatile
keyword in Java is used to indicate that a variable's value will be modified by different threads. When a variable is declared as volatile
, it ensures that its value is always read from the main memory, and not from the thread's local cache, thereby ensuring visibility of changes across threads.
Key Characteristics of volatile
- Visibility: Ensures that changes to a variable are visible to all threads.
- Atomicity: Does not guarantee atomicity of compound actions. For example, operations like incrementing a
volatile
variable are not atomic. - No Caching: Prevents the caching of the variable in thread-local memory.
When to Use volatile
The volatile
keyword is useful when you have a variable that is shared between multiple threads, and you need to ensure that changes made by one thread are visible to other threads. It is typically used for flags, state variables, or any variable that is read and written by multiple threads.
Example of Using volatile
Consider a scenario where a flag is used to control the termination of a thread:
public class VolatileExample {
private volatile boolean running = true;
public void run() {
while (running) {
System.out.println("Thread is running...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("Thread stopped.");
}
public void stop() {
running = false;
}
public static void main(String[] args) throws InterruptedException {
VolatileExample example = new VolatileExample();
Thread thread = new Thread(example::run);
thread.start();
Thread.sleep(5000); // Let the thread run for a while
example.stop(); // Stop the thread
}
}
Explanation
-
Declaration:
private volatile boolean running = true;
The
running
variable is declared asvolatile
, ensuring that any changes made to it are visible to all threads. -
Read and Write:
- The
run
method continuously checks the value ofrunning
. - The
stop
method sets the value ofrunning
tofalse
.
- The
-
Thread Behavior:
- The main thread starts a new thread that runs the
run
method. - After 5 seconds, the main thread calls the
stop
method to change therunning
variable tofalse
, causing therun
method to exit the loop and stop the thread.
- The main thread starts a new thread that runs the
Volatile vs. Synchronized
-
Volatile:
- Ensures visibility of changes across threads.
- Does not provide atomicity for compound actions.
- Does not block other threads; lightweight compared to synchronized.
- Suitable for simple flags or state variables.
-
Synchronized:
- Ensures visibility and atomicity.
- Provides exclusive access to a block of code or method.
- Can lead to thread contention and performance overhead due to locking.
- Suitable for complex operations involving multiple steps or shared data structures.
Example of Volatile Limitation
The volatile
keyword does not ensure atomicity for compound actions. For instance:
public class VolatileCounter {
private volatile int count = 0;
public void increment() {
count++; // Not atomic
}
public int getCount() {
return count;
}
public static void main(String[] args) {
VolatileCounter counter = new VolatileCounter();
// Create multiple threads that increment the counter
for (int i = 0; i < 1000; i++) {
new Thread(counter::increment).start();
}
// Wait for a while to let threads finish
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// Output the count
System.out.println("Count: " + counter.getCount()); // Output might not be 1000
}
}
In this example, the increment operation (count++
) is not atomic, and multiple threads may interfere with each other, leading to incorrect results. To ensure atomicity, you need to use synchronization or AtomicInteger
.
Conclusion
The volatile
keyword in Java is a useful tool for ensuring visibility of shared variables across threads. It is lightweight compared to synchronization but does not provide atomicity for compound operations. Understanding when and how to use volatile
is essential for writing correct and efficient multithreaded programs.