Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Volatile vs Synchronized
2.1.
Volatile
2.2.
Synchronized
3.
Volatile in Java vs C/C++
3.1.
Example in Java
3.2.
Example in C
4.
Frequently Asked Questions
4.1.
Can volatile guarantee thread safety in Java?
4.2.
When should I use volatile instead of synchronized?
4.3.
Is volatile in Java more efficient than synchronized?
5.
Conclusion
Last Updated: Apr 2, 2024
Easy

Volatile Keyword in Java

Author Rinki Deka
0 upvote
Crack Google SDE interview : Essential projects
Speaker
Saurav Prateek
SDE-2 @
20 Jun, 2024 @ 01:30 PM

Introduction

When we talk about programming, especially in Java, there are some key concepts that really help in making our applications efficient & reliable. One such concept is the use of the volatile keyword. This tiny word plays a big role in dealing with variables in a multi-threaded environment. Volatile makes sure that changes to a variable are always visible to all threads by flushing the value directly back to main memory. 

Volatile Keyword in Java

This article will help you learn what the volatile keyword is, its importance, and how it compares to other synchronization techniques. 

Volatile vs Synchronized

When it comes to managing the state of variables in multi-threaded Java applications, two main keywords come into play: volatile & synchronized. Both are essential but serve different purposes.

Volatile

The volatile keyword is all about visibility. It tells the JVM (Java Virtual Machine) that a thread accessing a volatile variable must always merge its own private copy of the variable with the master copy in the main memory. This means that changes made by one thread are immediately visible to other threads. It's like a group of friends sharing a notepad. If one writes a new message on the notepad, everyone else can see it right away because there's only one notepad, and it's shared among all.

Here's a simple code snippet to demonstrate the use of volatile:

public class SharedObject {
    // Declare a volatile variable
    volatile int sharedCounter = 0;


    public void incrementCounter() {
        sharedCounter++;  // Directly updates the master copy
    }
}

Synchronized

On the other hand, synchronized is all about mutual exclusion. It ensures that only one thread can execute a block of code at a time. This is more like taking turns. Imagine a single bathroom that only one person can use at a time. When one person is using it, others have to wait their turn. This is what synchronized does; it makes sure that when one thread is working with a piece of code, no other thread can come in and mess things up.

Here's how you might use synchronized in a method:

public class Counter {
    private int count = 0;
 // Synchronized method to increment count
    public synchronized void incrementCount() {
        count++;  // Only one thread can execute this at a time
    }
}


While volatile ensures visibility of changes, synchronized also ensures atomicity (completeness) of operations. Using volatile is more lightweight compared to synchronized, which comes with a performance cost due to locking overhead. However, volatile cannot be used in all situations, especially when the operation involves more than one step (e.g., check-then-act operations). That's where synchronized or other synchronization techniques come into play.

Get the tech career you deserve, faster!
Connect with our expert counsellors to understand how to hack your way to success
User rating 4.7/5
1:1 doubt support
95% placement record
Akash Pal
Senior Software Engineer
326% Hike After Job Bootcamp
Himanshu Gusain
Programmer Analyst
32 LPA After Job Bootcamp
After Job
Bootcamp

Volatile in Java vs C/C++

Understanding the volatile keyword requires a bit of cross-language comparison, especially between Java & C/C++. While volatile exists in both Java and C/C++, its usage & implications differ slightly due to the nature of these languages and their memory models.

In Java, volatile is all about visibility & ordering. When a variable is declared as volatile in Java, it ensures that any thread that reads the variable will see the most recent write to that variable. It's a way to say, "Hey, this variable might be changed by other threads, so always go straight to the main memory to read its latest value." This guarantees a 'happens-before' relationship, meaning changes to a volatile variable are immediately visible to all other threads, and reads/writes to volatile variables cannot be reordered.

Example in Java

public class VolatileExample {
   // volatile variable
   
   volatile boolean keepRunning = true;
   
 public void runExample() {
       new Thread(() -> {
           int count = 0;
           while (keepRunning) {
               count++;
           }

           System.out.println("Thread finished. Counted up to " + count);

       }).start();

       // Main thread sleeps for a bit and then stops the loop

   try {
           Thread.sleep(100);

           keepRunning = false;

           System.out.println("Flag set to false.");

       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}

 

In C/C++, volatile is also used to indicate that a variable's value can change unexpectedly. However, in C/C++, it's more about preventing the compiler from optimizing away variable accesses. For instance, in embedded systems, certain memory-mapped peripheral registers need to be read or written in a specific order, and using volatile ensures the compiler won't reorder or optimize these accesses. This does not guarantee atomicity or visibility in the same way as in Java, especially considering C/C++'s more complex memory model and the lack of built-in thread memory model before C++11.

Example in C

#include <stdio.h>
volatile int flag = 0;

int main() {
   // Simulated peripheral register access
   
   while(flag == 0) {
       // Waiting for the flag to change
   }

   printf("Flag changed!\n");
   return 0;
}

 

In summary, while volatile serves a similar purpose in both Java & C/C++, the memory models & thread handling of these languages mean it plays out differently. In Java, it's part of the language's concurrency mechanism, providing a easy way to ensure visibility and ordering. In C/C++, it's more about telling the compiler to treat variable access, avoiding optimizations that could mess with the intended operation, especially in low-level programming contexts.

Frequently Asked Questions

Can volatile guarantee thread safety in Java?

Volatile can ensure visibility of changes across threads, but it doesn't guarantee atomicity. This means for operations that need to read, modify, and write values back, simply marking a variable as volatile isn't enough for thread safety. For such cases, you might need to use synchronized blocks or other atomic constructs.

When should I use volatile instead of synchronized?

Use volatile when you need to ensure that changes to a single variable are visible to all threads, and the operation on that variable doesn't involve multiple steps (read-modify-write). It's lighter than synchronized but more limited in use. Synchronized is better for complex operations or when working with multiple variables.

Is volatile in Java more efficient than synchronized?

Yes, volatile is generally more efficient than synchronized because it doesn't involve locking. However, its use cases are more limited. If you only need to ensure visibility and don't need atomicity for multi-step operations, volatile can be a more performant choice.

Conclusion

In this article, we learned the importance and use of the volatile keyword in Java, contrasting it with synchronized and exploring its similarities and differences with its usage in C/C++. We started with a basic understanding of what volatile means in Java - ensuring visibility of changes to variables across threads without the need for synchronization mechanisms like locking. We then compared volatile with synchronized, highlighting that volatile is best for simple flag-like variables, while synchronized is needed for more complex operations involving multiple steps or variables.

You can refer to our guided paths on the Coding Ninjas. You can check our course to learn more about DSADBMSCompetitive ProgrammingPythonJavaJavaScript, etc. Also, check out some of the Guided Paths on topics such as Data Structure and AlgorithmsCompetitive ProgrammingOperating SystemsComputer Networks, DBMSSystem Design, etc., as well as some Contests, Test Series, and Interview Experiences curated by top Industry Experts.

Previous article
Generic Comparator in Java
Next article
Arrow Operator Java
Live masterclass