-3

I am learning volatile variable. I know what volatile does, i wrote a sample program for Volatile variable but not working as expected.

Why the program is going in infinite loop? If the variable "isTrue" is volatile then it should always get the value from Main memory? why the thread is caching it?

Can someone please explain why? and also if can provide the solution for that...(I will not put isTrue in while loop)

I have one VolatileSample class as:-

    public class VolatileSample{

static volatile boolean isTrue=true;

public VolatileSample(boolean is){
    isTrue=is;
}

public void print() {
    boolean b=isTrue;
    while (b) {
        System.out.println("In loop!");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

public void setFalse() {
    boolean b=false;
    System.out.println("Setting value as false");
    isTrue=b;
}

}

Created two threads as:-

   public class Thread1 extends Thread{

VolatileSample sample;
public Thread1(VolatileSample sample){
    this.sample=sample;
}
public void run(){
    sample.print();
}

} And

   public class Thread2 extends Thread{

VolatileSample sample;

public Thread2(VolatileSample sample){
    this.sample=sample;
}
public void run(){
    sample.setFalse();
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}

Main class:-

   public class Test {  
public static void main(String[] args) throws InterruptedException {
    // TODO Auto-generated method stub
    VolatileSample sample=new VolatileSample(true);

    Thread1 t1=new Thread1(sample);
    Thread2 t2=new Thread2(sample);

    t1.start();
    t2.start();
}

}

Art
  • 414
  • 7
  • 24

3 Answers3

4

You're using while(b) in print method when you should use while(isTrue). b is a local variable that isn't updated, while isTrue is the volatile variable that can be updated externally. This should work:

//using this you will understand meaning of volatile
while (isTrue) {
    System.out.println("In loop!");
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Note that Java is pass by value, not by reference. Updating the value of isTrue field won't directly update the value of b local parameter in print method. If you don't want to use while(isTrue) (very odd), then just update the value of b inside the loop:

while (b) {
    System.out.println("In loop!");
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    //you need to use the volatile variable in order to understand volatile
    b = isTrue;
}

Note that the loop will be infinite if you never update isTrue to false. Make the main method update the field after a naive delay:

public class Test {

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        VolatileSample sample=new VolatileSample(true);

        Thread1 t1=new Thread1(sample);
        Thread2 t2=new Thread2(sample);

        t1.start();
        t2.start();
        //naive delay
        Thread.sleep(2500);
        sample.setFalse();
    }
}

You say you don't want to use isTrue variable inside the while loop. Then, there's no way you update b variable inside print method after getting its value. Since b in this code will be true, then you will have an infinite loop. Period.

Seems that you want to synchronize this class through two threads, but that's not the point of volatile fields, for that you use synchronized modifier for methods or pieces of code, as pointed out by @JigarJoshi. You could have a better understanding by reading Simplest and understandable example of volatile keyword in java

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • 1
    I told that this i will not do..then what is the point of volatile? – Art Jun 19 '14 at 17:37
  • 1
    @RaghavTandon you're missing basic Java programming concepts: java is pass by value, not by reference. That will do. – Luiggi Mendoza Jun 19 '14 at 17:38
  • Thanks buddy for ur response...i added b = isTrue; but still going in infinite loop.. – Art Jun 19 '14 at 17:43
  • @RaghavTandon I don't see any part in your code where you call `VolatileSample#setFalse`. How do you expect to stop the `while` loop if you never set `isTrue` to `false`? Again, you're failing at basic Java. – Luiggi Mendoza Jun 19 '14 at 17:45
  • can u modify the part of the program which you are trying to say...so that it doesnt go in infinite loop. Dont use `code` isTrue in while loop.. – Art Jun 19 '14 at 17:47
  • Can u see the thread2 where i am calling setFalse on the same instance of VolatileSample... – Art Jun 19 '14 at 17:48
  • 1
    @RaghavTandon *don't use `isTrue` in while loop* it would be **impossible**. Your main problem is about Java basics, not about understanding volatile, and I cannot fix that. – Luiggi Mendoza Jun 19 '14 at 17:51
  • @Luggi i got ur point...n thanks for ur reply...let me understand volatile more... – Art Jun 19 '14 at 18:00
  • it is working now..Can you just explain my last doubt that if the same thing i am doing by starting a new thread Thread2 then it is not working..but when doing in Main method itself it is working..Why? – Art Jun 19 '14 at 18:04
  • @RaghavTandon it is a race condition. When `Thread2#run` is executed, code in `Thread1#run` had executed, so `boolean b=isTrue;` was executed and `b` will be `true`. Note that the order of the execution of methods cannot be guaranteed, so in any of your executions `Thread2#run` may execute before `Thread1#run` and the application finished w/o even executing the code inside the `while` loop in `print` method. – Luiggi Mendoza Jun 19 '14 at 18:30
1

You are actually setting false to local variable

public void setFalse() {
    boolean b=false; // <-- this is local variable
    System.out.println("Setting value as false");
    isTrue=b; // <-- this is shared but you don't check on it in your while loop
}

not to the shared one

You might want to iterate while loop by checking isTrue

jmj
  • 237,923
  • 42
  • 401
  • 438
  • ok...thanks for ur reply..can u give me an example where i can actually see volatile keyword working. I want example where one thread updates and other reads from memory and if the keyword is not volatile then it should go in infinite loop.... – Art Jun 19 '14 at 17:40
  • see here: http://stackoverflow.com/questions/17748078/simplest-and-understandable-example-of-volatile-keyword-in-java – jmj Jun 19 '14 at 17:42
0

@LuiggiMendoza is right: You should not try to understand volatile before you have learned the basic features of the language such as, how method calls work.

But If you insist... Try running this, and then try it again after taking out the volatile keyword from the timeToStop declaration. I can't guarantee what will happen in your JVM on your OS; The Java language spec does not guarantee what will happen when you don't say volatile. But, in my JVM on my OS, the program never terminates if the variable is not volatile.

class Foo {
    private static volatile boolean timeToStop = false;
    private static long count = 0;

    public static void main(String[] argsIgnored) throws InterruptedException {
        Thread busyThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (! timeToStop) {
                    count += 1;
                }
            }
        });
        busyThread.start();
        Thread.sleep(1000);
        timeToStop = true;
        busyThread.join();
        System.out.println(count);
    }
}
Solomon Slow
  • 25,130
  • 5
  • 37
  • 57