Java – static variable vs volatile
I'm just asking questions from a thread perspective... I may have answered many times, but please help me understand this
Refer to the post volatile vs static in Java here
Ask that a static variable value will also be a value for all threads, so why should we choose volatile? I found the following examples:
public class VolatileExample { public static void main(String args[]) { new ExampleThread("Thread 1 ").start(); new ExampleThread("Thread 2 ").start(); } } class ExampleThread extends Thread { private static volatile int testValue = 1; public ExampleThread(String str){ super(str); } public void run() { for (int i = 0; i < 3; i++) { try { System.out.println(getName() + " : "+i); if (getName().compareTo("Thread 1 ") == 0) { testValue++; System.out.println( "Test Value T1: " + testValue); } if (getName().compareTo("Thread 2 ") == 0) { System.out.println( "Test Value T2: " + testValue); } Thread.sleep(1000); } catch (InterruptedException exception) { exception.printStackTrace(); } } } }
Output:
Thread 1 : 0 Test Value T1: 2 Thread 2 : 0 Test Value T2: 2 Thread 1 : 1 Test Value T1: 3 Thread 2 : 1 Test Value T2: 3 Thread 1 : 2 Test Value T1: 4 Thread 2 : 2 Test Value T2: 4
If I delete static from testvalue, the result is:
Thread 1 : 0 Test Value T1: 2 Thread 2 : 0 Test Value T2: 1 Thread 1 : 1 Test Value T1: 3 Thread 2 : 1 Test Value T2: 1 Thread 1 : 2 Test Value T1: 4 Thread 2 : 2 Test Value T2: 1
Why did thread 2 not read the updated value? If it has to be static, what is the use of volatile?
Someone can link to a good example of volatile, where the variable is not declared static
thank you
Solution
The problem is that it is not atomic The code should use atomicinteger Using static variables, both threads try to update the same value, which is actually three operations: get, 1 and store This means that there are competing conditions between the two threads and they cover each other
Static and changeable do different things Static makes the fields associated with this class correspond to object instances Volatile forces any field to be read or written across the memory barrier This allows multiple threads to read and update common fields, but it does not protect you from multiple operations If you make variables not static, you don't need volatile because each thread uses its own field instance
You should use atomicinteger This wraps a volatile int, but also provides special handling for incremental operations:
private static AtomicInteger testValue = new AtomicInteger(1); ... testValue.incrementAndGet();
When multiple threads share non static fields, you need a volatile For example, if you move testvalue into the volatileexample class, and then pass the same instance of the volatileexample class to two threads so that they can access testvalue