1

I am trying to understand the volatile keyword and wrote a dummy program to test it.

public class SharedObjects {

    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();

        Thread thread1 = new Thread(runnable, "Thread 1");
        Thread thread2 = new Thread(runnable, "Thread 2");

        thread1.start();
        thread2.start();

        System.out.printf("%s: %d\n", Thread.currentThread().getName(), runnable.count);
    }
}
public class MyRunnable implements Runnable {
    public volatile int count = 0;

    @Override
    public void run() {
        for (int i = 0; i < 1000000; i++) {
            count++;
        }

        System.out.printf("%s: %d\n", Thread.currentThread().getName(), count);
    }
}

Output:

main: 1024
Thread 2: 831910
Thread 1: 902879

I think with or without volatile keyword, the result of the last finished thread should be at least 1000000 (the number of times of the loop), but it doesn't with volatile keyword.

If I remove the volatile keyword, it always gives a number at least 1000000, like

main: 1063
Thread 2: 1086742
Thread 1: 1086742
SiAce
  • 357
  • 3
  • 15
  • 2
    Volatile is not the same as atomic. – khelwood Jan 01 '21 at 18:27
  • @khelwood, yeah, I think volatile means visibility, but if it's atomic, the result should be 2000000. – SiAce Jan 01 '21 at 18:29
  • @NathanHughes, I mean the result of the last finished thread as stated in the question – SiAce Jan 01 '21 at 18:31
  • 3
    `++` is not atomic. It involves reading the variable value, adding one to it, then writing that value back to the variable. If two threads are trying to do that at the same time, then sometimes the variable has increased between when you read it and when you write to it. So you end up decreasing (or not increasing) its value. – khelwood Jan 01 '21 at 18:34
  • @khelwood, thanks for your help, now I kind of know why it could be less than 1 million, but I am still not sure of the distinct behaviors between with/without `volatile` in this situation. – SiAce Jan 01 '21 at 18:43
  • @SiAce You have to understand the difference between Data race and Race condition. Volatile is about Data race/to prevent undefined behavior/to guarantee visibility (see JLS 17.4.5) . Atomicity is about Race condition, about a defect of an algorithm with well defined/known, but wrong behavior (yes, he should remember/just know that ++ on a primitive isn't atomic). If you need both visibility+atomicity at once, use a lock (standard RWLock or synchronization block) with plain fields or AtomicXXX types for increment/decrement/CAS operations – AnatolyG Jan 05 '21 at 15:36

0 Answers0