1

I have a really strange problem with java under Debian. On windows this works:

boolean X=true;
while(X);

This code performs a loop while X is true, when i set X to false the while loop ends. The problem is that on Debian the SAME code, when i set X to false, the while loop does not stop.

If I modify the the code:

boolean X=true;
while(X) {
    System.out.println("hello");
}

This code works fine on Debian but only if I add the print statement. If I try i++ for example it doesn't work correctly, only with the print statement it works.

Why is my code handled differently on a different OS?

Math
  • 3,334
  • 4
  • 36
  • 51
Salvosnake
  • 83
  • 10
  • Are you sure that the loop actualy start? maybe if a while loop is no point it might be ignored – Anthony Raymond May 06 '14 at 12:51
  • 2
    Can you post the full code you're using when you're setting X to false? – David May 06 '14 at 12:51
  • 1
    post the actual code that doesn't work. – Dan May 06 '14 at 12:51
  • Java is Java. Please be more explicit, cannot recreate your issue with what you have provided here. – Elliott Frisch May 06 '14 at 12:52
  • 2
    I am trying my telepathic skills. I think your program has at least two threads (one where the while-loop spins and the other where you set the flag X to false). If a variable is read/written from more than a single thread one needs to make an effort for changes made in one thread to be visible others. If you make your X volatile or replace it with AtomicBoolean it should do the trick. Has nothing to do with Debian. – bobah May 06 '14 at 12:54
  • 1
    What are the Java versions involved? – Gerald Schneider May 06 '14 at 12:54
  • 2
    last I checked the default "java" on linux was gcj, which isn't Java and hasn't been updated in years. It's also a bug riddled monstrosity. – jwenting May 06 '14 at 12:57
  • And are you building both versions on the same OS or once on each OS? – indivisible May 06 '14 at 12:57
  • I wonder if `while(X) { continue; }` makes a difference. – 2rs2ts May 06 '14 at 12:58
  • java -version and javac -version would provide a lot of clarity here... – jwenting May 06 '14 at 12:59
  • @jwenting: bit off topic but: https://wiki.debian.org/Java/ – indivisible May 06 '14 at 13:00
  • i use jdk 8 now, i set the X variable to false on different thread , the code is this, the real code is more big but the problem is that, i have tryed to compile the code on windows and execute it on Debian, is same.. oh sorry for my bad english i hope is understable ;-) – Salvosnake May 06 '14 at 13:04
  • @user3608219 Are you saying that you created the `.class` files on Windows, then ran them on Debian? – 2rs2ts May 06 '14 at 13:07
  • @bobah was right and that if you are changing the boolean in a different thread you need to make it volatile – Dan May 06 '14 at 13:09
  • i mean i have tryed to compile all under debian and also i have tryed to compile under windows and execute the jar file on debian, but the same file on windows work on debian not if i not add the printing statment, i ahve tryed also to compile with print statment under widnows, when i run on debian work fine – Salvosnake May 06 '14 at 13:10
  • possible duplicate of [Loop doesn't see changed value without a print statement](http://stackoverflow.com/questions/25425130/loop-doesnt-see-changed-value-without-a-print-statement) – Boann Aug 23 '14 at 10:21

2 Answers2

2

If non-volatile variable is accessed from other thread, the behavior may be unpredictable: it may be cached on the current thread. Try to define X as volatile:

volatile boolean X = true;

Take a look at: Do you ever use the volatile keyword in Java?

Community
  • 1
  • 1
Dmitry Ginzburg
  • 7,391
  • 2
  • 37
  • 48
0

I found this to give interesting results depending on the processor's architecure x86 vs 64bits.

public class WhileTrueTest
{
    boolean keepGoing = true;
    volatile boolean volatileKeepGoing = true;

    public static void main( String[] args ) throws InterruptedException
    {
        new WhileTrueTest().go();
    }

    private void go() throws InterruptedException
    {
        final Thread tNormal = new InnerNormal();
        final Thread tVolatile = new InnerVolatile();
        tNormal.start();
        tVolatile.start();
        Thread.sleep( 1000 );
        keepGoing = false;
        volatileKeepGoing = false;
        Thread.sleep( 1000 );
        System.out.printf("Threads shouldn't be alive. Are they? Normal:%s Volatile:%s", 
           tNormal.isAlive(), 
           tVolatile.isAlive());
        System.out.println();
        System.exit(1);

    }

    class InnerNormal extends Thread
    {
        @Override
        public void run()
        {
            while(keepGoing) {}
        }

    }

    class InnerVolatile extends Thread
    {
        @Override
        public void run()
        {
            while(volatileKeepGoing) {}
        }
    }        
}
Nicolas C
  • 944
  • 1
  • 10
  • 22