This post would demo how to do the thread communication by using volatile. If you want to know the wait-notify communication, you can refer to the previous article.
- Java 1.8
2.1 The java heap memory and thread memory
As we know, the object we defined in class level would be allocated in the java heap memory, and every thread has its own memory, which is located at the stack, usually in the CPU buffer memories.
When we access the heap variable from thread, it really copies the value of the object and access it from local. As the following picture shows:
2.2 The volatile keyword introduction
By using volatile , you can make the variable seen by all the threads, and the changes to the volatile variable would be seen immediately by all the threads, there is no latency for the synchronization.
Using volatile forces all accesses (read or write) to the volatile variable to occur to main memory, effectively keeping the volatile variable out of CPU caches. This can be useful for some actions where it is simply required that visibility of the variable be correct and order of accesses is not important. –by Lawrence Dol.
2.3 What happens without volatile in multithreading environment?
Here I write an example without volatile, you can see that Not using volatile would cause Unsynchronized problems in multithreading environment.
The above code explanations:
- The above example just define a global flag and starts two worker threads that monitors the flag, if the main thread changes the flag, the workers should stop immediately.
- line 1: we define a variable named flag in the heap space. And all threads would monitor this flag , if it changed to false, then all threads should stop immediately.
- line 2: change the heap variable from main thread
Run the above code sometimes, we would find the output like this:
We found that,the workers stopped Unsynchronizedly. That is :
- The main thread changed the flag to false in the heap memory
- Worker1 copied the value to local stack memory and stopped
- After a while(only 1 millisecond later) the worker2 copied the value to local stack memory and stopped
But if we change the flag to volatile like this:
Then all the workers thread should see the flag and react to the change without hesitation.
We run the code for 20 times,the result is in line with expectations.
2.4 The volatile is not synchronized!
Volatile only make the heap variable visible to all threads, e.g. They would get the change infomation immediately when the change happens. But if the heap variable is mutable and all thread read and write it concurrently, it would cause many problems.
Here we supply an example about the problem:
In the above example, we defined a volatile variable named count,which would be changed by the main thread/worker threads. The worker thread just sleep for a while and then add the count,The main thread start the workers and then add the count and print the count at last.
Our expectation is the count should equals to 30000.
But we get this:
The reason I think is:
- Volatile can not assure the synchronization read/write of the threads
- Multiple threads would write to this count concurrently, it would cause problem
So if we want the synchronization of the threads, we need lock.
New synchronized version with volatile:
Run the code several times, we got the same result:
Volatile keyword only make variable visible to all threads, and we can NOT do synchronization by it. If you need to read/write same variable by multithreads simultaneously, use lock to do this job.
You can find detail documents about the java stream here: