tags:

views:

250

answers:

6

As i understand, if we declare a variable as volatile, then it will not be stored in the local cache. Whenever thread are updating the values, it is updated to the main memory. So, other threads can access the updated value.

But in the following program both volatile and non-volatile variables are displaying same value.

The volatile variable is not updated for the second thread. Can anybody plz explain this why testValue is not changed.

class ExampleThread extends Thread {
    private int testValue1;
    private volatile int testValue;
    public ExampleThread(String str){
      super(str);
    }
    public void run() {
    if (getName().equals("Thread 1 "))
    {
        testValue = 10;
        testValue1= 10;
        System.out.println( "Thread 1 testValue1 : " + testValue1);
        System.out.println( "Thread 1 testValue : " + testValue);
    }
    if (getName().equals("Thread 2 "))
    {
        System.out.println( "Thread 2 testValue1 : " + testValue1);
        System.out.println( "Thread 2 testValue : " + testValue);
    }               
}
}

public class VolatileExample {
    public static void main(String args[]) {
        new ExampleThread("Thread 1 ").start();
        new ExampleThread("Thread 2 ").start();
    }
}


output:
Thread 1 testValue1 : 10
Thread 1 testValue : 10
Thread 2 testValue1 : 0
Thread 2 testValue : 0
+1  A: 

testValue is a member variable, so the two threads see two independent copies. volatile is relevant when two or more threads have a reference to the same object.

Make testValue static and volatile will have an effect. However, you may not (and probably will not) see that effect, as it is highly dependent on timing, scheduling and caching strategies which are out of your (or even the VM's) control. A missing volatile will only rarely have an effect, which makes such bugs very hard to catch. It will only be seen when a thread updates the value and the second thread reads the value and the value is still in the cache in either of the two threads.

Thomas Lötzer
It's actually a member variable, not a local. See polygene's answer.
Steven Mackenzie
can u plz explain with example...i m not getting
sap
@Stevenyou're right. Updated my answer.@sapsee my updated answer
Thomas Lötzer
+1  A: 

May be you lost static keyword?

Vitaly Dyatlov
i am asking about volatile, not static...Static anyways work fine with or without volatile
sap
+5  A: 

Your variables are confined to a single thread, so there is no other thread accessing them. Thus volatile makes no difference.

If you declared them static, they would be shared between different threads. However, even then you may not be able to observe the difference between your volatile and nonvolatile variable. Quote from Java Concurrency in Practice, chap. 3.1.4:

The visibility effects of volatile variables extend beyond the value of the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable. So from a memory visibility perspective, writing a volatile variable is like exiting a synchronized block and reading a volatile variable is like entering a synchronized block.

In your case, the code happens to modify the volatile variable first, so the updated value of the other variable may not be visible to the other thread. So far, so good.

However, since you are printing out the values of the variables from the same thread which modified them, you won't see any difference anyway.

Update2: Try this modified version (note: I have not tested it):

class ExampleThread extends Thread {
    private static int testValue1;
    private static volatile int testValue;
    private int newValue;

    public ExampleThread(String str, int newValue){
      super(str);
      this.newValue = newValue;
    }
    public void run() {
      for (int i = 0; i < 10; i++) {
        System.out.println(getName() + " testValue1 before update: " + testValue1);
        System.out.println(getName() + " testValue before update: " + testValue);
        testValue = i * newValue;
        testValue1 = i * newValue;
        System.out.println(getName() + " testValue1 after update: " + testValue1);
        System.out.println(getName() + " testValue after update: " + testValue);
        sleep(10);
      }               
    }               
}

public class VolatileExample {
    public static void main(String args[]) {
        new ExampleThread("Thread 1 ", 5).start();
        new ExampleThread("Thread 2 ", 10).start();
    }
}

Update: regarding the visibility of static fields - again from the same tome (chap 16.2.3):

[...] statically initialized objects require no explicit synchronization either during construction or when being referenced. However, this applies only to the as-constructed state - if the object is mutable, synchronization is still required by both readers and writers to make subsequent modifications visible and to avoid data corruption.

Péter Török
i am asking about volatile, not static...Static anyways work fine with or without volatile
sap
You may want to clarify that your phrase "confined to a single thread" is referring to the Thread instance, not the thread itself (to which we might confine a variable using a ThreadLocal).
Steven Mackenzie
@Steven Mackenzie In the above example, the variables in question are private members which can only be accessed by their owner (which happens to be a Thread instance). So they are obviously confined to the thread associated with that instance. ThreadLocal is not the only way to achieve thread confinement.
Péter Török
@sap no it does not - see my update.
Péter Török
+2  A: 

ExampleThread 1 and ExampleThread 2 are different objects.

In one of them you assigned 10 to both int fields and that's why you see that output for first thread.

In second you didn't assign anything to int fields so you get 0s.

Roman
can u modify for exactly how we can implement it for volatile
sap
+3  A: 

This has nothing to do with volatile; those are two separate instances of ExampleThread, with their own copies of testValue1 and testValue, which are instance fields (not static class variables, which are "shared" between all instances).

polygenelubricants
can u plz explain about volatile functionality
sap
You should read up on Java Memory Model, and the book "Java Concurrency in Practice".
polygenelubricants
+1  A: 

Here is an example showing a variable that is accessed by two threads. The StarterThread thread sets the variable started when the thread starts. The WaiterThread waits for the variable started to be set.

public class Main
{
    static /*volatile*/ boolean started = false;

    private static class StarterThread extends Thread
    {
        public void run()
        {
            started = true;
        }
    }

    private static class WaiterThread extends Thread
    {
        public void run()
        {
            while (!started)
            {
            }
        }
    }

    public static void main(String[] args)
    {
        new StarterThread().start();
        new WaiterThread().start();
    }
}

If started is not volatile, then there is no synchronization point that guarantees that WaiterThread will ever get the updated value of the started variable. Consequently, the WaiterThread thread could potentially run "indefinitely".

Matthew T. Staebler