0

I'm playing with volatile keyword in Java and I have this code that tries to show that a thread doesn't see changes introduced by another thread unless we declare data as volatile. I was expecting that the code below will never terminate as I haven't declared the shared data as volatile. Any ideas why this code actually terminates?

public class VolatileTest {

    public static void main(String[] args) throws InterruptedException {
        var holder = new Holder();
        new Thread(() -> {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) { }
            for(int i = 0; i<100000; i++) {
                holder.counter++;
            }
        }).start();
        var t = new Thread(() -> {
            while(holder.counter < 10000) {
                System.out.println("Jestem w pętli");
                try {
                    Thread.sleep(400);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        t.join();
    }

    static class Holder {
        int counter = 0;
    }

}
Jens
  • 67,715
  • 15
  • 98
  • 113
  • 1
    Where do you use the `volatile` keyword? BTW: Never write `catch (InterruptedException e) { }` exception should be handled, atleast logged – Jens Feb 28 '20 at 13:48
  • 1
    Threads are allowed to cache values of non-volatile variables. That's not a guarantee that they won't see changes. – khelwood Feb 28 '20 at 13:50
  • This answer explain why your code "works" without the `volatile` keyword https://stackoverflow.com/a/30956634/5862990 – andergtk Feb 28 '20 at 13:58
  • 1
    This is why testing multi-threaded programs for correctness is a hard problem. The Java Language Specification guarantees that your program will behave a certain way if you obey certain rules. But, It does _NOT_ guarantee that your program will misbehave if you break the rules. Worst-case scenario is where you test the hell out of some software, it passes all of your tests, you ship it to an important client, and then the **** hits the fan six months later when they upgrade their OS. It happens. Don't ask me how I know! – Solomon Slow Feb 28 '20 at 15:03

1 Answers1

0

Thread 1 MAY not see change from the Thread 2 immediately if you don't use volatile, but eventually once in the future, that will happen when Thread 2 empty CPU cache to main memory. In your example, if you use volatile on counter field, writing thread will always write to main memory when you call holder.counter++ and reading thread will read from main memory every time you call holder.counter < 10000.

Spasoje Petronijević
  • 1,476
  • 3
  • 13
  • 27