0

I am working on a very simple Java code to get some experience on threads. shirt is a variable that has a color attribute.

while(true){ 
    if (shirt.isColorBlue()) {           
        System.out.println("The shirt is finally blue.");
    }
}

During the while loop above, a thread that is running in parallel updates the shirt's color. However, inside of the if block never executes. I did some alterations to see some other conditions:

while(true){ 
    if (shirt.isColorBlue()) {           
        System.out.println("The shirt is finally blue.");
    }

    try {
        Thread.sleep(1000);
    }  catch (InterruptedException e) { }   
}

If I do it like above, the code works (inside the if block gets executed). From this, I understand that the other thread updates the shirt variable after the while starts to iterate. But shouldn't it be still okay since the ideal scenario is "the while looping many many times and the if block executing whenever the other thread updates the shirt variable"?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
codertryer
  • 359
  • 3
  • 12
  • 5
    Make the variable `volatile` or use means of synchronization. Java doesn't gurantees visibility of variables between multiple threads without that. – dan1st Jan 10 '23 at 17:01
  • In addition to the visibility issue you might have a misconception in "the if block executing whenever the other thread updates the shirt variable". Not knowing all of your code you seem to have one thread that constantly updates the shirt's color and one (the one you showed) that constantly checks it. That means the if-condition is checked many times until it finally becomes true. However, note that while you have 2 threads it's not guaranteed that they will be executed round-robin so you don't know when either of them will run. – Thomas Jan 10 '23 at 17:09
  • @dan1st should i make it static too? – codertryer Jan 10 '23 at 17:11
  • @Thomas The other thread actually updates the shirt once – codertryer Jan 10 '23 at 17:13
  • @dan1st But doesn't volatile just provide the change to be seen immediately? In my case, I don't care for it to be like that. It is fine by me to see the update after a couple of while loops. – codertryer Jan 10 '23 at 17:26
  • 1
    The problem is that if the variable isn't `volatile`, there is no guarantee that the other thread ever sees the change, so it has to be volatile (or you need to use another way that establish a happens-before relationship between the threads). – Mark Rotteveel Jan 10 '23 at 17:40
  • "*It is fine by me to see the update after a couple of while loops*" there is no guarantee *when* reading thread will *refresh* values it holds (or if it will refresh at all - like shown in first example). Using `volatile` solves this problem. This may interest you https://jenkov.com/tutorials/java-concurrency/volatile.html (I strongly recommend whole blog and YT channel of this guy) – Pshemo Jan 10 '23 at 17:40
  • Dupe: [Loop doesn't see value changed by other thread without a print statement](//stackoverflow.com/q/25425130). If you use sysout.println() or Thread.sleep is not a real difference in this context. – Tom Jan 10 '23 at 17:49
  • @codertryer `volatile` makes sure changes to a variable are immediately visible to other threads. Without it, the variable might never get "published" to other threads. – dan1st Jan 10 '23 at 18:51
  • 1
    Don't get the wrong idea from what those other guys are telling you about `volatile`. It is _one_ way to ensure that the change in `color` is seen by the other thread, but it is not the _only_ way. Another way would be through proper use of `synchronized` blocks or `ReentrantLock`. What those things all have in common is, they establish a "[happens before](https://www.geeksforgeeks.org/happens-before-relationship-in-java/)" relationship between the two threads. Anything that establishes "happens before" will ensure that the one thread can see what the other thread did. – Solomon Slow Jan 10 '23 at 20:28
  • Like [Solomon Slow said](https://stackoverflow.com/questions/75073363/a-variables-update-that-is-done-by-a-different-thread-is-not-seen-in-a-whiletr#comment132485217_75073363), there are multiple solutions. Another, and my preference, is [`AtomicBoolean`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html). To learn about Java concurrency, see [this book](https://jcip.net/). – Basil Bourque Jan 10 '23 at 23:54

0 Answers0