Consider this example from GeeksForGeeks:
public class VolatileKeyword {
    private static final Logger LOGGER = Logger.getLogger(VolatileKeyword.class);
    private static int MY_INT = 0;
    public static void main(String[] args) {
        new ChangeListener().start();
        new ChangeMaker().start();
    }
    static class ChangeListener extends Thread {
        @Override public void run() {
            int local_value = MY_INT;
            while (local_value < 5) {
                // (A)
                if (local_value != MY_INT) {
                    LOGGER.info("Got Change for MY_INT : " + MY_INT);
                    local_value = MY_INT;
                }
            }
        }
    }
    static class ChangeMaker extends Thread {
        @Override public void run() {
            int local_value = MY_INT;
            while (MY_INT < 5) {
                LOGGER.log(Level.INFO, "Incrementing MY_INT to " + (local_value + 1));
                MY_INT = ++local_value;
                try {
                    Thread.sleep(500);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
As stated in the article, the output you see consistently is:
Incrementing MY_INT to 1
Incrementing MY_INT to 2
Incrementing MY_INT to 3
Incrementing MY_INT to 4
Incrementing MY_INT to 5
Which is due to the fact that the ChangeListener is always reading MY_INT from its thread-local cache. (I tested this to be sure).
However, if you were to replace // (A) with any of the following:
- Thread.currentThread().isAlive();
- Thread.sleep(0)
- Thread.interrupted()
- System.out.print("");
- adding a volatileintegerxtoChangeListenerand replacing// (A)withx += MY_INT
among other things, you would get the same output as you would by making MY_INT a volatile variable. That is,
Incrementing MY_INT to 1
Got Change for MY_INT : 1
Incrementing MY_INT to 2
Got Change for MY_INT : 2
Incrementing MY_INT to 3
Got Change for MY_INT : 3
Incrementing MY_INT to 4
Got Change for MY_INT : 4
Incrementing MY_INT to 5
Got Change for MY_INT : 5
What is is the common denominator with the operations I listed above that is causing the thread cache to clear?
EDIT: The last two suggestions clearly hit volatile or synchronized code leading to the "cache reset", but what about the others?
 
    