6

I am only asking in threading perspective...probably answered many times but please help me to understand this.

With reference to post here Volatile Vs Static in java

asking a static variable value is also going to be one value for all threads, then why should we go for volatile? I found following example :

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 remove the static from the testValue, result obtained:

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 thread 2 is not reading the updated value? If it has to be made static , whats the use of volatile?

Can someone give link to a good example of volatile where that variable is not declare static.

Thanks

Community
  • 1
  • 1
Dhananjay
  • 734
  • 1
  • 9
  • 14

4 Answers4

4

The use of volatile is to ensure that all threads see the same value at the same time. Essentially it is saying that this variable should never be cached.

It is difficult to demonstrate in code because cacheing strategies change from cpu to cpu and from JRE to JRE.

What volatile is saying to the JRE is If you are ever tempted to cache this value because you think you could make the code run a little faster by doing so ... DONT! ... I know MUCH more about programming than you do and I know without a shadow of a doubt that if you do you will break my code..

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
4

The problem is that the ++ is not atomic. The code should use AtomicInteger instead. With the static variable, both threads are trying to update the same value and the ++ is actually 3 operations: get, +1, and store. This means that there is a race condition between both of the threads and they are overwriting each other.

Why thread 2 is not reading the updated value? If it has to be made static , whats the use of volatile?

static and volatile do different things. static makes the field associated with the class as opposed to the object instance. volatile forces any read or write of the field to cross a memory barrier. This allows multiple threads to read and update a common field but this does not protected you from multiple operations. If you make the variable not be static then you would not need the volatile since each thread would be working with it's own instance of the field.

You should use AtomicInteger. This wraps a volatile int but also provides special handling of increment operations:

private static AtomicInteger testValue = new AtomicInteger(1);
...
testValue.incrementAndGet();

Can someone give link to a good example of volatile where that variable is not declare static.

You would need a volatile on a non-static field when it was shared by multiple threads. For example, if you moved the testValue up into the VolatileExample class and then passed the same instance of the VolatileExample class into both threads so they could access testValue.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • Thanks for you valuable insight, i will test the same, keeping the variable elsewhere. – Dhananjay Feb 25 '13 at 14:41
  • Just to reiterate, you can't do a `++` on a `volatile` regardless if it is static or not @Dhananjay. – Gray Feb 25 '13 at 14:45
  • i tried putting the variable outside the Runnable class.
    ' public class Account { public double balance = 0; public static void main(String... s){ Account aAccount =new Account(); DepositThread aDepositThread1=new DepositThread (aAccount); Thread thread1=new Thread(aDepositThread1,"thread1"); DepositThread1 aDepositThread2=new DepositThread1(aAccount); Thread thread2=new Thread(aDepositThread2,"thread2"); thread1.start(); thread2.start(); } } ' But if we are passing the same object in two thread, It will get the updated value anyways?
    – Dhananjay Feb 25 '13 at 16:52
0

In this case, when tou removed the static modifier you changed the variable, because now, each ExampleThread has its own testValue, for that, the storage value is different for each thread instance.

Meaning of static modifier:

Sometimes, you want to have variables that are common to all objects. This is accomplished with the static modifier. Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable...

Reference: Understanding Instance and Class Members

About volatile, if you try a different kind of test, moving the testValue variable to the class VolatileExample, like this:

 public class VolatileExample {
    private volatile int testValue = 1;
 ...
 }

Then, remove the testVariable from ExampleThread and run the code. Its output should be like the first one.

Meaning of volatile modifier:

Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads

Reference: Atomic Access

Jose Renato
  • 705
  • 5
  • 18
0

Your last question "Can someone give link to a good example of volatile where that variable is not declare static." made to understand this concept clearly and i came with an example.

    public class VolatileExample {

   // public static volatile int testValue = 1;
    public  int nonstatic=8;
    public static void main(String args[]) {
        VolatileExample volatileExample=new VolatileExample();
        new ExampleThread("Thread 1 ",volatileExample).start();
        new ExampleThread("Thread 2 ",volatileExample).start();
    }

}
class ExampleThread extends Thread {
VolatileExample volatileExample;
    public ExampleThread(String str,VolatileExample volatileExample){
        super(str);
        this.volatileExample=volatileExample;
    }
    public void run() {
        for (int i = 0; i < 3; i++) {
            try {
                if (getName().compareTo("Thread 1 ") == 0)
                {
                   volatileExample.nonstatic++;
                    System.out.println( "Test Value T1: " + volatileExample.nonstatic);


                }
                if (getName().compareTo("Thread 2 ") == 0)
                {
                    System.out.println( "Test Value T2: " + volatileExample.nonstatic);
                    Thread.sleep(1);
                }
               // Thread.sleep(1000);
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }
        }
    }
}

now please see the change by making public int nonstatic=8; volatile

Following would be the output when it is made volatile,

Test Value T1: 9 Test Value T1: 10 Test Value T1: 11 Test Value T2: 11 Test Value T2: 11 Test Value T2: 11

Process finished with exit code 0

Following is the result if it is made non-volatile: Test Value T1: 9 Test Value T2: 9 Test Value T1: 10 Test Value T1: 11 Test Value T2: 11 Test Value T2: 11

Process finished with exit code 0

Observation:Since Volatile keyWord makes the thread to directly write it in main memory,thread gets back faster to the loop hence when it is made volatile,thread1 completed its task faster and got back to the loop even before thread2 started its turn.

On the other side,making it non-volatile,makes the thread to update its locl cache and then report it to the main memory...so during this cycle,thread2 entered the race.

PLz note,i have "non-static" variable in VolatileExample class not in the ExampleThread to demonstrate this one.

Your other question is : Why thread 2 is not reading the updated value? If it has to be made static , whats the use of volatile?

Well,if u make it testvalue non-static,then its nothing but two different objects Thread1 and Thread2 of class ExampleThread working on their own varibles testvalue.... so volatile doesnt really matter..

Sriharsha g.r.v
  • 456
  • 5
  • 13