Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: For loop in while loop not running unless println statement included

I am trying to run a for loop inside an infinite while loop. The code doesn't run as intended when there's no print statement, but when there is a print statement, it runs fine. Here is the code:

class Test implements Runnable{
  public static int varint = 0;
  public static void main(String args[]){
    Thread x = new Thread(new Test());
    int i;
    x.start();
    while(true){
      System.out.println("Hello World"); //If this isn't included, 
                                        //the exit statement isn't executed
      for(i=0;i<varint;i++){
        System.out.println("Exit");
        System.exit(0);
      }
    }
  }

  public void run(){
    try{
      Thread.sleep(5000);
    } catch(Exception e){
      System.out.println("Caught");
    }
    varint = 1;
  }
}

This is just a small example taken from a much bigger loop. How can I fix this?

like image 682
Serket Avatar asked Sep 11 '20 22:09

Serket


People also ask

What is a while loop in Java?

Java while loop is a control flow statement that allows code to be executed repeatedly based on a given Boolean condition. The while loop can be thought of as a repeating if statement.

What happens if the while loop returns false in Java?

If it returns false, it will end the while loop. The Java Do-While loop is almost the same in While Loop. While loop executes the code inside the bracket if the condition statement returns to true, but in the Do-While loop, the code inside the do statement will always be called.

What is the difference between a while loop and an exit loop?

The difference lies in the fact that if the condition is true at the starting of the loop the statements would still be executed, however in case of while loop it would not be executed at all. This is an exit-controlled loop because of the fact that it checks the condition after the statements inside it are executed.

What is looping statement in Java?

Looping statements are also common in programming. These are used if you are executing the same line of codes repeatedly. In order to minimize the lines of codes, we use looping statements. ? //enter your code here that will be called repeatedly. A Java For loop contains three parts inside the parenthesis.


2 Answers

You have a data race. One of the threads write to varint and the other reads varint with no explicit synchronization. varint is not declared volatile. According to Java memory model, there is no guarantee the reading thread will ever see the that varint was changed.

It works when you add the println because println uses synchronization internally, which makes varint visible to the running thread.

Either use a locking to read/write varint, or declare it volatile.

This is a good source for the Java memory model and volatiles:

http://tutorials.jenkov.com/java-concurrency/java-memory-model.html#visibility-of-shared-objects

like image 110
Burak Serdar Avatar answered Oct 11 '22 04:10

Burak Serdar


The main thread executing the loop in this avatar is not guaranteed to see any updates to varint. So varint can be updated to 1 or 100 but there would still be no guarantees for main thread to be able to see the updates.

In order to guarantee memory visibility, use a volatile or synchronization primitives.

Please see the following link from an architect of Java 5 Concurrency. This article explains: "Status Flags and Volatile"

On the other hand, the reading thread in certain cases (intermittently as in your case when you add the print) might see the update and it might seem the program is behaving correctly. Such kind of visibility issues are extremely hard to track if it makes it to production.

like image 1
Khanna111 Avatar answered Oct 11 '22 03:10

Khanna111