Search code examples
javajava.util.concurrent

a concurrency problem makes volitile not work


B thread reads two global variables, A thread writes two global variables.

How could second much bigger than first?

public class ThreadTest {
    private static volatile int first = 0;
    private static volatile int second = 0;

    private static class ReaderThread extends Thread {
        @Override
        public void run() {
            while (first < 10000) {
                if (first != second) {
                    System.out.println("ThreadB------first = " + first + ", second = " + second);
                }
            }
            System.out.println("ThreadB------first = " + first + ", second = " + second);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new ReaderThread().start();
        Thread.sleep(1000L);
        while (first < 10000){
            first++;
            second++;
        }
    }
}
ThreadB------first = 3296, second = 3535
ThreadB------first = 7615, second = 7663
ThreadB------first = 8179, second = 8192
ThreadB------first = 8635, second = 8662
ThreadB------first = 9151, second = 9177
ThreadB------first = 10000, second = 10000
ThreadB------first = 10000, second = 10000

So what happened, and how to fix this problem?


Solution

  • After the 'if' is satisfied, you execute some relatively slow-running string concatenations. Some unknown length of time (maybe hundreds of machine cycles) can elapse between reading 'first' and reading 'second' while evaluating, left to right, the expression for the argument to the println call.

    Try recoding as

       int f = first, s = second;
       if (f != s) {
            System.out.println("ThreadB------first = " + f + ", second = " + s);
       }
    

    and see what it looks like then.

    The bigger issue is, if this is a fragment of some real code, it does not seem like it can provide any useful synchronization. Each integer has immediately-visible effects, but there is no synchronization between the two values. The only guarantee I can see is that, as written, you cannot ever see a value of 'second' that is less than the value of 'first'.