Sunday, September 17, 2023

How Volatile in Java works? Example of volatile keyword in Java

What is a volatile variable in Java and when to use the volatile variable in Java is a famous multi-threading interview question in Java interviews? Though many programmers know what is a volatile variable they fail on the second part i.e. were to use volatile variables in Java as it's not common to have a clear understanding and hands-on on volatile variables in Java. In this tutorial, we will address this gap by providing a simple example of the volatile variable in Java and discussing when to use the volatile variable in Java. Anyway,  the volatile keyword in Java is used as an indicator to Java compiler and Thread that do not cache the value of this variable and always read it from the main memory.

So if you want to share any variable in which read and write operation is atomic by implementation like reading and write in an int or a boolean variable then you can declare them as a volatile variable. 

From Java 5 along with major changes like Autoboxing, Enum, Generics, and Variable arguments, Java introduces some change in the Java Memory Model (JMM), Which guarantees visibility of changes made from one thread to another also as "happens-before" which solves the problem of memory writes that happen in one thread can "leak through" and be seen by another thread.

The Java volatile keyword cannot be used with method or class and it can only be used with a variable. Java volatile keyword also guarantees visibility and ordering, after Java 5 writes to any volatile variable happens before any read into the volatile variable.

By the way use of volatile keywords also prevents the compiler or JVM from the reordering of code or moving away from them from the synchronization barrier.




What is volatile variable in Java? An Example

To Understand the example of volatile keyword in Java let’s go back to the Singleton pattern in Java and see double-checked locking in Singleton with Volatile and without the volatile keyword in java.

/**
 * Java program to demonstrate where to use Volatile keyword in Java.
 * In this example Singleton Instance is declared as volatile variable to ensure
 * every thread see updated value for _instance.
 * 
 * @author Javin Paul
 */
public class Singleton{
private static volatile Singleton _instance; //volatile variable 

public static Singleton getInstance(){

   if(_instance == null){
            synchronized(Singleton.class){
              if(_instance == null)
              _instance = new Singleton();
            }

   }
   return _instance;

}

If you look at the code carefully you will be able to figure out:
1) We are only creating instances one time
2) We are creating instances lazily at the time the first request comes.


If we do not make the _instance variable volatile then the Thread which is creating an instance of Singleton is not able to communicate other thread, that instance has been created until it comes out of the Singleton block, so if Thread A is creating Singleton instance and just after creation lost the CPU, all other thread will not be able to see the value of _instance as not null and they will believe it's still null.

volatile variable in Java with Example

Why? because reader threads are not doing any locking and until the writer thread comes out of the synchronized block, the memory will not be synchronized and the value of _instance will not be updated in the main memory. 

With Volatile keyword in Java, this is handled by Java himself and such updates will be visible by all reader threads. So in Summary apart from synchronized keywords in Java, a volatile keyword is also used to communicate the content of memory between threads.




Let’s see another example of a volatile keyword in Java

most of the time while writing game we use a variable bExit to check whether the user has pressed the exit button or not, the value of this variable is updated in the event thread and checked in the game thread, So if we don't use volatile keyword with this variable, Game Thread might miss an update from event handler thread if it's not synchronized in Java already.

The volatile keyword in java guarantees that the value of the volatile variable will always be read from the main memory and the "happens-before" relationship in the Java Memory model will ensure that the content of memory will be communicated to different threads.

private boolean bExit;

 while(!bExit) {
    checkUserPosition();
    updateUserPosition();
 }


In this code example, One Thread (Game Thread) can cache the value of "bExit" instead of getting it from the main memory every time and if in between any other thread (Event handler Thread) changes the value; it would not be visible to this thread. Making boolean variable "bExit" as volatile in java ensures this will not happen.

Also, If you have not read it already then I also suggest you read the topic about volatile variables from Java Concurrency in Practice book by Brian Goetz, one of the must-reads to truly understand this complex concept.

When to use volatile variable in Java





When to use Volatile variable in Java? Example

One of the most important things in the learning of volatile keywords is understanding when to use a volatile variable in Java. Many programmers know what is volatile variable and how does it work but they never really used a volatile modifier for any practical purpose. Here are a couple of examples to demonstrate when to use the volatile keyword in Java:

1. You can use the Volatile variable if you want to read and write long and double variables atomically. long and double both are 64-bit data types and by default writing of long and double is not atomic and platform dependence. 

Many platforms perform write in long and double variable 2 step, writing 32 bit in each step, due to this it's possible for a Thread to see 32 bit from two different writers. You can avoid this issue by making the long and double variable volatile in Java.


2. A volatile variable can be used as an alternative way of achieving synchronization in Java in some cases, like Visibility. with volatile variable, it's guaranteed that all reader threads will see the updated value of the volatile variable once the write operation is completed, without volatile keyword different reader thread may see different values.



3. volatile variable can be used to inform the compiler that a particular field is subject to be accessed by multiple threads, which will prevent the compiler from doing any reordering or any kind of optimization which is not desirable in a multi-threaded environment. 

Without a volatile variable, the compiler can re-order the code, free to cache value of volatile variable instead of always reading from main memory. like the following example without volatile variable may result in an infinite loop

private boolean isActive = thread;
public void printMessage(){
  while(isActive){
     System.out.println("Thread is Active");
  }
} 


without the volatile modifier, it's not guaranteed that one Thread sees the updated value of isActive from other threads. The compiler is also free to cache the value of isActive instead of reading it from the main memory in every iteration. By making isActive a volatile variable you avoid these issues.


4. Another place where a volatile variable can be used is to fix double-checked locking in the Singleton pattern. As we discussed in Why should you use Enum as Singleton that double-checked locking was broken in Java 1.4 environment?




Important points on Volatile keyword in Java

1. The volatile keyword in Java is the only application to a variable and using a volatile keyword with class and method is illegal.

2. volatile keyword in Java guarantees that the value of the volatile variable will always be read from the main memory and not from Thread's local cache.

3. In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables).

4. Using the volatile keyword in Java on variables reduces the risk of memory consistency errors because any write to a volatile variable in Java establishes a happens-before relationship with subsequent reads of that same variable.

5. From Java 5 changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable in Java, it sees not just the latest change to the volatile variable but also the side effects of the code that led up the change.

6. Reads and writes are atomic for reference variables are for most primitive variables (all types except long and double) even without the use of volatile keyword in Java.

7. Access to a volatile variable in Java never has a chance to block, since we are only doing a simple read or write, so unlike a synchronized block we will never hold on to any lock or wait for any lock.

8. Java volatile variable that is an object reference may be null.

9. Java volatile keyword doesn't mean atomic, it's a common misconception that after declaring volatile ++ will be atomic, to make the operation atomic you still need to ensure exclusive access using synchronized method or block in Java.

10. If a variable is not shared between multiple threads, you don't need to use a volatile keyword with that variable.




Difference between synchronized and volatile keywords in Java

What is the difference between volatile and synchronized is another popular core Java question asked on multi-threading and concurrency interviews. Remember volatile is not a replacement of a synchronized keyword but can be used as an alternative in certain cases. 

Here are a few differences between volatile and synchronized keywords in Java.

1. The volatile keyword in Java is a field modifier while synchronized modifies code blocks and methods.

2. Synchronized obtains and releases the lock on the monitor’s Java volatile keyword doesn't require that.

3. Threads in Java can be blocked for waiting for any monitor in case of synchronization, that is not the case with the volatile keyword in Java.

4. Synchronized method affects performance more than a volatile keyword in Java.

5. Since volatile keyword in Java only synchronizes the value of one variable between thread memory and "main" memory while synchronized synchronizes the value of all variables between thread memory and "main" memory and locks and releases a monitor to boot. Due to this reason, synchronized keyword in Java is likely to have more overhead than volatile.

6. You can not synchronize on the null object but your volatile variable in Java could be null.

7. From Java 5 writing into a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire


In short, the volatile keyword in Java is not a replacement of a synchronized block or method but in some situations is very handy and can save performance overhead which comes with the use of synchronization in Java. If you like to know more about volatile I would also suggest going thorough FAQ on Java Memory Model here which explains the happens-before operations quite well.



Other Java concurrency tutorials from Javarevisited you may like

Thanks for reading this article so far. If you like this Java volatile tutorial and example then please share it with your friends and colleagues. If you have any questions or feedback then please drop a note. 

P.S. - If you are new to the Java Programming field and need a free course to learn essential Java multithreading tools, libraries, and concepts then I highly suggest you join this free Java Multithreading course for beginners. This is a free Udemy course to learn Java Multithreading from scratch.

Now, over to you; What is difference between atomic, volatile, and synchronized variable in Java? Can you replace volatile with atomic variables?

57 comments :

Anand Vijayakumar said...

This one is a Gem Javin!!!

Keep up the good work.

Anand.

Anonymous said...

hi, what is difference between volatile and synchronized keyword in java ? Can we use volatile in place of synchronized ? what will happen if we don't make variable volatile in Java ?

Javin @ String vs StringBuffer said...

Hi Anonymous, Volatile and Synchronized are completely different with each other. you can not use volatile keyword with methods while synchronized keyword can be used. similarly synchronized keyword can not be applied to variable while you can make variable volatile. to read more about synchronized read my post How Synchronization works in Java

Barchist said...

Why not we can use volatile keyword with method ? why only variable needs to be volatile ? yes it may look some insane questions but I just want to know basics of volatile keyword ?

Anonymous said...

Volatile in Java is more of a documentation keyword, I never seen much usage of volatile keyword in most of project, what I have seen is synchronized and synchronized.

Aban said...

Hi,

For understanding and testing purpose I write a small pice of code as following:

VolatileTest.java
-------------------

public class VolatileTest extends Thread {

private volatile int testValue;
private volatile boolean ready;

public VolatileTest(String str) {
super(str);
}

public void run() {
for (int i = 0; i < 3; i++) {
try {
if (getName().equals("T1")) {
ready = true;
testValue = i;
System.out.println(getName() + " :: " + ready + " :: " + testValue);
}
if (getName().equals("T2")) {
System.out.println(getName() + " :: " + ready + " :: " + testValue);
}
Thread.sleep(1000);
} catch (InterruptedException exception) {
exception.printStackTrace();
}
}
}
}

TestVol .java
--------------
public class TestVol {
public static void main(String[] args) {
new VolatileTest("T1").start();
new VolatileTest("T2").start();
}
}

I am getting following output:
T1 :: true :: 0
T2 :: false :: 0
T1 :: true :: 1
T2 :: false :: 0
T1 :: true :: 2
T2 :: false :: 0

Can you please help me to understand, why this result is comming. As per my understanding, I should get "T2 :: true :: 0" (second line).

Regards,
Aban

Javin @ spring interview questions answers said...

Hi Aban, line 2 is correct since you are using two separate object of VolatileTest default value for boolean ready is false which is displaying. try using one object and share it between two threads.

Issamu said...

So to me it only makes sense using VOLATILE with a static field, is this assumption right?
As in Aban example, there is no need for testValue and ready being volatile because each instance of thread would have its own version of these fields, it's not shared between them.

Chris said...

you double-check-lock in the singleton, but it states on the java sun documentation (which you've linked to) that this doesnt work...

http://java.sun.com/developer/technicalArticles/Programming/singletons/

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

love the blog though

Javin @ spring interview questions answers said...

Hi Chris, Thanks for your comment. double check lock example will not work prior to Java5 but with change in Java memory model and guarantee provided by volatile keyword in Java , double checked locking will work if we make Singleton instance volatile. as I have mentioned in point 5 "From Java 5 changes to a volatile variable are always visible to other threads"

Peter Lawrey said...

This covers the issues well.

I would comment that the simplest singleton pattern is

enum Singleton { INSTANCE; }

its thread safe and lazy loading.

Javin @ race condition in java said...

@Unknown,Thanks for comment. Glad to know that you like this Java volatile example and tutorial. you may like my other post on threading as well e.g. Why wait and notify are defined in Object class

Anonymous said...

I read your blog often, however, I think you made a mistake in the following line

"....all other thread will not be able to see value of _instance as not null and they will believe its still null."


It should be more like " all other threads will see the partially constructed value of _instance and return the value thinking it is not null."

This is according to wikipedia..http://en.wikipedia.org/wiki/Double-checked_locking

Anonymous said...

Can a volatile variable in Java be static ? If not why ?

What difference it make to mark a volatile variable final ?

Anonymous said...

As others have pointed out this blog is misleading. Volatile in your example has nothing to do with ensuring the field is non-null (this guarantee would actually cause a problem in the original Java memory model - see link below).

As I found this blog by googling "java volatile" people are probably reading it and getting incorrect information.

The example you provided requires a volatile because the reading of a volatile (assuming later Java memory model) guarantees that a previous write to the volatile has completed, and this in turn guarantees the object was constructed completely because of "as-if-serial" preservation and its rules regarding volatile. Without a volatile, _instance could be written to in a thread and "leaked" out of its local memory into another thread before the object is constructed fully, because "as-if-serial" rules in that case would allow reordering within the thread as long as that thread isn't affected.

You should read this and re-write the blog (or just link to this page which explains it anyway):
http://www.ibm.com/developerworks/library/j-jtp03304/

It also explains why you probably shouldn't bother with double checked locking, something missing here.

Existentior said...

This is very good stuff. You are a good programmer, Javin. There are not many like you out there. My sincere thanks to you for this article. It helps many people understand the details.

Chatar said...

This is not true Jatin ->
3. In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables).

To make read/ write automatic you need to you CAS operation which are implemented using Atomic*** in Java 1.5 concurrent package or last choice is explicit synchronization.


tang07059 said...

Do you know the difference between Hashtable (synchronized) and Volatile HashSet (seems also synchronized)?

Anonymous said...

Thank you for your post!

my question is:
in your double locking example, if using volatile, do we still need to use synchronised block? it sounds like when thread A is calling 'getInstance()' for the first time, it will have the right to create the _instance obj. if other threads are trying to call getInstance(), they will find out A is modifying _instance and need to wait for thread A until it finishes the instantiation. Is that right?

Steve said...

@Anonymous, yes, you need to use synchronized block to ensure that multiple instance of same object is not created. By making singleton instance volatile, you are ensuring that you don't see half backed object, this was the problem before Java introduces memory model and happens before rule. As per happens-before rule, Write to volatile variable happens before every subsequent read of that volatile variable.

Anonymous said...

what do you mean by after creation lost the CPU

Anonymous said...

Amazing explanation! Thanks for that.

In the differences section point 5, you say that -
"synchronized synchronizes the value of all variable between thread memory and "main" memory"

Isn't this incorrect ? If it was true, then there would be no need for Volatile keyword. (Since volatile is always used in conjunction with synchronized)

Javin @ abstract class interface interview questions said...

No, that's right and you don't need to use volatile keyword along with synchronized, they are for different purpose. volatile variable offers happens before guarantee that any write on volatile variable happens before subsequent read on that variable. It's different than synchronized keyword because it's doesn't provide mutual exclusion, and only gives visibility and ordering guarantee.

Anonymous said...

Thanks Javin.

- In the case of double checked locking in Singleton patten.
What is the need to declare a variable volatile, if the synchronized keyword takes care of synchronizing the value of all variable between thread memory and "main memory" ?


Read more: http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz2UEwqgU1g
Ok. In such case, lets tak what is the need of declaring

Javin @ Java Classloder Working said...

That's a good question Anonymous. If you look at code for double checked locking, you will see that first check is done outside synchronized block i.e. without any synchronization, which means, while one thread is initializing variable inside synchronized block, other thread can see half initialized Singleton instance, because first check is without any guarantee. By making _instance variable volatile, you ensure that write happens before read, which means when another thread reads _instance value, it won't see half initialized object. Hope this clears your doubt.

Anonymous said...

In one of the interview, I was asked that can we make an array volatile in Java? and they further grilled me on this i.e. will reading elements from array is volatile operation or not, what are the volatile read in case of array etc. I managed to answer that, because we can definitely make any array volatile but only assignment to array reference variable is volatile write e.g.

private volatile int[] numbers = new int[10];

is a volatile read operation and guarantees happens before relationship, but changing individual index is not a volatile write operation.

Unknown said...

The volatile modifier tells the compiler that the variable modified by volatile can be changed unexpectedly by other parts of your program. One of these situations involves multithreaded programs. In a multithreaded program, sometimes two or more threads share the same variable. For efficiency considerations, each thread can keep its own, private copy of such a shared variable

http://www.youtube.com/watch?v=y8_jrkHEZpg&list=PLrUFyg1unBb9bhxd9ck0LEL89UB_G6-ZJ&index=5

John said...

HI javin, for volatile test, is it necessary to mark volatile of data type int?
i attend 1 interview they asked me i have int variable, how to make thread safe? i told all the varaible data type are atomic operation except long & double, so no need to mark as volatile. interviewer told its wrong, for thread safe we need to mark as volatile. i m getng confused.

Unknown said...

This post is excellent for learning what is volatile and their application. Really appreciate Javin.
Sadly, it does not justify the heading given. It never explore how it works. Some newbie may get confused with the statement "reading the master copy". In a sense how volatile is different from static. Static works in same fashion. If possible please explain how it works in java and whats the internal difference.

Thank you.

RuGu said...

Hi Javin

The article is great. However I got confused with what you mentioned in two places(3 and 9) which seems(to me) opposite of each other.
Could you make it bit more clear

3. In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables).

9. Java volatile keyword doesn't means atomic, its common misconception that after declaring volatile ++ will be atomic, to make the operation atomic you still need to ensure exclusive access using synchronized method or block in Java.

Unknown said...

I am probably still missing some point regarding Singleton with volatile. I do understand the purpose of volatile and its effect there but I am not convinced that without volatile it is broken.Please correct me if I am wrong. If volatile is not present and thread A enters synchronized block and looses a cpu just after a creation of a instance. Ok thread B still see a _instance null which means it waits to acquire a monitor before creating an instance.When tread A exits sync block it propagates all variables to main memory, when thread B acquire a lock it synchronize its variables so gets updated _instance. That doesn't fulfill the condition, no instance creation. I see there possible performance penalty, yes. The other question would be if a different object would be used for synchronization that would be a different story.
Please correct me if I am missing something here.

Unknown said...

Hi,
I guess above example will work fine without volatile keyword also, because changes made in a synchronized block are also visible to other threads, please correct me If I am wrong.

Anonymous said...

What does volatile do? section in this post also explains it well
https://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#volatile

Anonymous said...

I have long been searching for practical example of volatile modifier in Java world, which goes beyond the classic explanation that volatile variables are always read from memory, so if you need that behavior, use volatile. Ok, I got that, but how about some practical use case scenarios? Well, after some research and lots of googling, I found that :

You should use volatile for three reasons :
- to avoid thread keep stale values in local cache, that's always the visibility guarantee.
- happens-before relationship, which means a volatile write will happens before any further volatile read
- to prevent re-ordering of code, which JVM or JIT does for performance reasons

Keep in this in mind, I find following practical scenarios where you can use volatile modifier :
1) In double checked locking code ( as given in this article), because the thread which is assigning value to _instance is different than the thread which is getting instance.

2) to make long and double read atomic in Java world. If you don't know, as per Java Memory Model a write to non-volatile double and long variable completes in two steps, where each step writes the 32-bit value. It's possible that one thread can see half value written by another thread. You can prevent this by using volatile keyword.

3) word tearing

renjith alexander said...

Regarding the usage of volatile in double checked locking:

I don't understand how making the _instance variable volatile, would help. As far as I understand, when a thread leaves a sync block, it will commit all the variables it has changed, to the main memory. Likewise, a thread entering a sync block would always read the values(which it is going to use or change) from the main memory afresh(as it would not know how much time it had been waiting to get into the sync block).

In essence, the thread which enters sync block, immediately after the thread which created the instance left the sync block, will definitely see the _instance as non-null, irrespective of whether _instance was declared as volatile or not.

Bhupender Giri said...

Hi,
Thanks for your post but point no. 3 & 6 are contradictory under "Important points on Volatile keyword in Java" section.
In my opinion, Volatile only guarantees "Visibility" but not atomicity. Since long/double variable does not support atomicity so possible solution for them would be using Atomic* apis.

Anonymous said...

Accoring to servlet specification, container makes one instance. and specification says that "do not mark service() method as a syncronized, because at that time the servlet container cannot use the instance pool approach. One instance and pooling, it's confused. When I see your first example, for singleton, I really know how to make pooling for singleton objects. Volatile keyword supply this functionality for multi processor computers behind the scenes. Thank you.

Haf said...

Nice post !! What i learnt from this post in short ----> if two threads are both reading and writing to a shared variable, then using the volatile keyword for that is not enough. You need to use a synchronized in that case to guarantee that the reading and writing of the variable is atomic. Reading or writing a volatile variable does not block threads reading or writing. For this to happen you must use the synchronized keyword around critical sections. Instead use Atomic classes from concurrent package for primitive wrappers.

Unknown said...

If the threads have the working memory, does that not mean they are having their own memory to some extent? can someone please explain this?

javin paul said...

@Lakshmi, that true. Thread has their own memory and that's called Stack memory. Every thread has Stack memory which you can configure using -Xss parameter.

Unknown said...

I have one queston in mind. Suppose I make a variable volatile and that variable is being used by two threads separately in a method which doing some calculation and return the new value of the variable.

Now how this thing is atomic as the second thread is reading the variable before it gets changed from the first thread. It didn't got the updated value of the variable from the first thread.

Please help me understand this.

Anonymous said...

Can we use volatile modifier with interface variables ?

Anonymous said...

Hi all,
Why did the author use synchronized block rather than synchronized method?
I mean, was there any clear advantage for that?
Thanks

javin paul said...

@It reduces the scope of locking i.e lock will be held for code which really needs locking and for less time. This will result in better performance.

chrome said...

I think the reason why _instance in Singleton class must be volatile you described here is incorrect.
The real reason is other thread might read partial initialized instance, which might cause error.
see https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java

Unknown said...

In one point you mentioned below :

You can use Volatile variable if you want to read and write long and double variable atomically. long and double both are 64 bit data type and by default writing of long and double is not atomic and platform dependence. Many platform perform write in long and double variable 2 step, writing 32 bit in each step, due to this its possible for a Thread to see 32 bit from two different write. You can avoid this issue by making long and double variable volatile in Java.

And also below, can you or anyone other can explain the conflicts that I m seeing between the points.
Java volatile keyword doesn't mean atomic, its common misconception that after declaring volatile ++ will be atomic, to make the operation atomic you still need to ensure exclusive access using synchronized method or block in Java.

Anonymous said...

Finally, I think i know volatile.

Thank you.

Unknown said...

you are saying that variables involving atomic operations need to be made volatile...but consider making a variable volatile that gets incremented in one thread.
Normally, you want atomicity of compound statement execution, and for that you need to use synchronized (or the new java.util.concurrent classes). It is worth pointing out that increment (i.e. ++) and similar operations are not atomic in Java. So incrementing a volatile variable volatileVar++ is NOT thread-safe. If you need thread-safe semantics i.e. no possibility of multiple threads corrupting the variable value by having the updates unexpectedly interfere with each other, then you need to use a synchronized block to increment a variable, e.g. synchronized(LOCK){myVar++}, regardless of the overheads this causes.

javin paul said...

Hello @unknown, I agree, volatile is not for atomicity, what I was saying that if you are using long or double variable in your thread safe class then make them volatile. The read and write of double variable, not incrementing or decrementing is also not atomic but volatile makes that atomic.

Unknown said...

Really excellent post, Thanks for this explanation

SKumar said...

First, thank you for the post. This post is very intriguing. It made me practice a lot of different scenarios and learn a lot.

I was able to test the following scenario:
Case1: Singleton creation using a synchronized block, volatile variable but no double-checked locking (create multiple instance 1/10 times)

However, following scenarios produced the single instance in spite of running the test case multiple times
Case2: Using a synchronized block, volatile variable and double-checked locking
Case3: Using a synchronized block and double-checked locking but no use of volatile variable

Case2 is pretty clear to me now.
But, case 3 must produce multiple instances at least once after testing it so many times.

Here is code for it. Please, let me know if you have any better way to test it.
// Singleton class creation
package volatileuse;

public class SingletonCreationWithoutUsingVolatile {
private static SingletonCreationWithoutUsingVolatile instance;

private SingletonCreationWithoutUsingVolatile() {
System.out.println("SingletonCreationWithoutUsingVolatile constructor called.");
}

public static SingletonCreationWithoutUsingVolatile getInstance(
String threadName) {
if (instance == null) {
synchronized (SingletonCreationWithoutUsingVolatile.class) {
if(instance==null){
instance = new SingletonCreationWithoutUsingVolatile();

System.out.println(threadName
+ " created new instance of this singleton class.");

}
}
}
return instance;
}
}


// Singleton creation concurrency test

package volatileuse;


import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingletonCreationWithoutUsingVolatileConcurrencyTest {
public static void main(String[] args) {
//long startTime= System.nanoTime();
CountDownLatch latch = new CountDownLatch(2);
long startTime= System.currentTimeMillis();
ExecutorService executors = Executors.newCachedThreadPool();
executors.execute(new Runnable() {
@Override
public void run() {
for(long i=1;i<999_999_999;i++){
//System.out.println("First Executor Thread count: "+i);
SingletonCreationWithoutUsingVolatile scuv = SingletonCreationWithoutUsingVolatile
.getInstance(Thread.currentThread().getName());

}
latch.countDown();
}
});
executors.execute(new Runnable() {

@Override
public void run() {
for(long i=1;i<999_999_999;i++){
//System.out.println("Second Executor Thread count: "+i);
SingletonCreationWithoutUsingVolatile scuv = SingletonCreationWithoutUsingVolatile
.getInstance(Thread.currentThread().getName());
}
latch.countDown();
}
});
executors.execute(new Runnable() {

@Override
public void run() {
//System.out.println("Third thread run.");
SingletonCreationWithoutUsingVolatile scuv = SingletonCreationWithoutUsingVolatile
.getInstance(Thread.currentThread().getName());
}
});
executors.execute(new Runnable() {

@Override
public void run() {
//System.out.println("Fourth thread run.");
SingletonCreationWithoutUsingVolatile scuv = SingletonCreationWithoutUsingVolatile
.getInstance(Thread.currentThread().getName());
}
});

executors.shutdown();
//long duration = System.nanoTime()-startTime;
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
long duration = System.currentTimeMillis()-startTime;
System.out.println("Time taken by program to execute "+duration+" milliseconds");

}
}


As case 3 is running fine in all cases, it makes me doubtful about the use of volatile variable in singleton creation.

Let me know if I missed something while writing the test case or a way to test the use of volatile would be helpful.

Anonymous said...

Can u give a real time example of volatile keyword ?

Jose Quijada said...

Regarding the first example, even if `_instance` was not volatile, reading threads can still see non-null when they do the first read of `_instance` in `if(_instance == null){`. This happens because, in the absence of some kind of synchronization the Java Memory Model (JMM) allows reordering of reads with respect to writes. In the last read of `_instance` in `return _instance;` the reader thread that read non-null in the first read can now read a null!!! Or it can see non-null `_instance` in both of those reads, but the internals of the Singleton might not be properly seen by the reading thread because there's no happens-before between the initialization of the Singleton by the writing thread and reads by the reader thread. In other words the reader thread(s) can see `_instance` in an inconsistent/invalid state which is not the same state that the writer thread left it in. The use of volatile in `_instance` addresses all these issues. If it were true that without volatile threads would always see null, then you wouldn't need volatile at all because even if reading threads saw null `_instance` incorrectly, once they got into `synchronize` block they would definitely correctly see non-null `_instance`. I just wanted to point out this correction to your reasoning for using volatile. Please see https://shipilev.net/blog/2014/safe-public-construction/, search for "One could think that after "check 1" had succeeded" and "Notice that we do several reads of instance", and read and study his analysis carefully. I would recommend reading entire article to gain deeper understanding of Java concurrency and how/why race conditions can arise.


Jose Quijada said...

Please this blog does not describe volatile correctly. I suggest reading Java Concurrency by Brian Goetz, Effective Java by Joshua Bloch and also this article, https://shipilev.net/blog/2014/safe-public-construction/. I see commenters giving kudos for excellent post, which is not the case. Without volatile in place `_instance` can still give non-null on the first read, and then a null on the second read to the same reading thread that wasn't the writing thread. If it was true that without volatile all reading threads would consistently see null `_instance`, then even without volatile all reading threads will see the non-null `_instance` quickly once they go go through the syncrhonized block after the writer thread finished. Please clarify this blog and/or correct it to avoid confusing especially those that are beginning in Java!!!

javin paul said...

Hello Jose, the point is volatile provides you the consistent behavior instead of unpredictable issues. Also Java Memory Model plays an important role in ensuring that every thread has a consistent view of volatile variable.

Unknown said...

Hi there. Maybe silly question as I'm just a beginner in Java, but isn't it a contradiction:

"3. In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables)."

"9. Java volatile keyword doesn't mean atomic"

Reads and writes are atomic when volatile is used but at the same time volatile doesn't mean atomic. How is it possible and what does it mean?

javin paul said...

it means operations like i++ is not atomic even if you declare the variable atomic.

Post a Comment