2

When learn the keyword volatile, I found https://stackoverflow.com/a/130320/4213589. I do some changes, but get confusing result. Here is my code:

import java.util.concurrent.*;

public class VolatileTest {

    // public static volatile int finished = 0; // 1
    public static int finished = 0; // 2

    public static void main(String[] args) throws ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Future<?> future = executor.submit(()->{
            while (finished == 0) {
                // when comment the below if-block, result confused
                if(Thread.currentThread().isInterrupted()){
                    System.out.println("???");
                    break;
                }
            }
        });

        executor.submit(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {
                ;
            } finally {
                finished = 1;
            }
        });

        System.out.println("Started..");

        try{
            future.get(5, TimeUnit.SECONDS);
            System.out.println("finished");
        } catch (TimeoutException | InterruptedException e){
            System.out.println("timeout!");
        } finally {
            future.cancel(true);
        }

        executor.shutdown();
    }
}

this code run normally, and output

Started..
finished

but when I comment the if-block in the first submit, output is

Started..
timeout!

But the process is still running, and seems loop no return.

So my question is: the non-empty loop will effect thread reading static variables?

赵浩翔
  • 643
  • 1
  • 5
  • 13

1 Answers1

3

If there is nothing in the while loop:

while (finished == 0) {}

the JVM is allowed to effectively execute this as:

if (finished == 0) while (true) {}

because it has no indication that finished might be changed in a way that it needs to read (because finished isn't volatile, and there's nothing inside the loop to otherwise create a happens-before).

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • Is it [JDK-8179334](https://bugs.openjdk.java.net/browse/JDK-8179334?focusedCommentId=14073039&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-14073039)? – 赵浩翔 May 06 '20 at 09:57
  • 1
    Just to make this clear: it does not matter whether the loop is empty or not. As long as the loop doesn’t contain a construct guaranteeing memory visibility, it may never notice the update. The effect of `if(Thread.currentThread().isInterrupted())` forcing an update when no interruption happened, is an implementation detail. It’s still not guaranteed. Only an actual interruption would guaranty memory visibility. – Holger May 07 '20 at 14:39