You should use sample code that can prove a "volatile" ad.

Currently, I cannot figure out when we should use volatile to declare a variable.

I do some research and have studied some materials about this for a long time, and I know that when a field is declared mutable, the compiler and the runtime note that this variable is general and that its operations should not be reordered with other memory operations.

However, I still cannot understand in which scenario we should use it. I mean, can someone provide some sample code that can prove that using "volatile" is beneficial or solves problems by comparing them without using?

+13
java multithreading concurrency volatile
Apr 28 2018-11-11T00:
source share
5 answers

Here is an example of why volatile needed. If you remove the volatile keyword, thread 1 will never end. (When I tested on Java 1.6 Hotspot on Linux, it really is - your results may vary because the JVM is not required to cache variables that are not marked volatile .)

 public class ThreadTest { volatile boolean running = true; public void test() { new Thread(new Runnable() { public void run() { int counter = 0; while (running) { counter++; } System.out.println("Thread 1 finished. Counted up to " + counter); } }).start(); new Thread(new Runnable() { public void run() { // Sleep for a bit so that thread 1 has a chance to start try { Thread.sleep(100); } catch (InterruptedException ignored) { } System.out.println("Thread 2 finishing"); running = false; } }).start(); } public static void main(String[] args) { new ThreadTest().test(); } } 
+12
Apr 28 '11 at 10:12
source share

The following is a canonical example of the need for volatility (in this case, for the str variable. Without it, the access point raises access outside the loop ( while (str == null) ), and run() never ends on most SMV servers.

 public class DelayWrite implements Runnable { private String str; void setStr(String str) {this.str = str;} public void run() {  while (str == null);  System.out.println(str); } public static void main(String[] args) {  DelayWrite delay = new DelayWrite();  new Thread(delay).start();  Thread.sleep(1000);  delay.setStr("Hello world!!"); } } 
+3
Apr 28 2018-11-21T00:
source share

Eric, I read your comments, and one in particular struck me

In fact, I can understand that the use of concept volatility is level. But for practice, I can't think of code that has concurrency problems without using mutable

The obvious problem you may encounter is reordering the compiler, for example, the more famous upgrade mentioned by Simon Nickerson. But suppose there will be no reordering, this comment may be valid.

Another problem that is volatile to solve is with 64-bit variables (long, double). If you write long or double, it is considered as two separate 32-bit storages. What can happen with simultaneous recording is that a maximum of 32 of one stream is written to 32 bits of the register, and the other stream writes at least 32 bits. Then you can have a long one that is neither one nor the other.

Also, if you look at the JLS memory section, you will notice it as a laid-back memory model.

This means that the records may not become visible (may be in the storage buffer) for a while. This can lead to outdated readings. Now you can say that this is unlikely, and it is, but your program is incorrect and has the potential for failure.

If you have an int that you increase the lifetime of the application, and you know (or at least think) that int wont overflow, you do not update it to the end, but it is still possible. In the event of a memory visibility problem, if you think that this should not affect you, you should know that it still can and can lead to errors in your parallel application that are extremely difficult to identify. Correctness is the reason for using volatiles.

+2
Apr 28 2018-11-11T00:
source share

The volatile keyword is quite complicated, and you need to understand what it does and does not work before using it. I recommend reading this section of the language specification , which explains it very well.

They highlight this example:

 class Test { static volatile int i = 0, j = 0; static void one() { i++; j++; } static void two() { System.out.println("i=" + i + " j=" + j); } } 

This means that at the time of one() j never more than i . However, another thread executing two() can print the value of j , which is much larger than i , because let say two() work and select the value of i . Then one() is executed 1000 times. Then the thread executing the two gets the scheduled schedule again and selects j , which is now much larger than the value of i . I think this example perfectly demonstrates the difference between volatile and synchronized - the updates for i and j are volatile, which means that the order in which they occur is consistent with the source code. However, two updates occur separately, and not atomically, so callers can see values ​​that look (for this caller) to be inconsistent.

In short: be very careful with volatile !

+1
Apr 28 2018-11-11T00:
source share

A minimalist example in java 8, if you remove the volatile keyword, it will never end.

 public class VolatileExample { private static volatile boolean BOOL = true; public static void main(String[] args) throws InterruptedException { new Thread(() -> { while (BOOL) { } }).start(); TimeUnit.MILLISECONDS.sleep(500); BOOL = false; } } 
0
Oct 30 '17 at 23:39 on
source share



All Articles