How to demonstrate Java instruction reordering problems?

后端 未结 3 567
借酒劲吻你
借酒劲吻你 2021-01-31 02:47

With Java instruction reordering the execution order of the code is changed by the JVM at compile time or run time, possibly causing unrelated statements to be executed out-of-o

3条回答
  •  眼角桃花
    2021-01-31 03:29

    Test

    I wrote a JUnit 5 test that checks whether instruction reordering took place after two threads terminate.

    • The test must pass if no instruction reordering happened.
    • The test must fail if instruction reordering occurred.

    public class InstructionReorderingTest {
    
        static int x, y, a, b;
    
        @org.junit.jupiter.api.BeforeEach
        public void init() {
            x = y = a = b = 0;
        }
    
        @org.junit.jupiter.api.Test
        public void test() throws InterruptedException {
            Thread threadA = new Thread(() -> {
                a = 1;
                x = b;
            });
            Thread threadB = new Thread(() -> {
                b = 1;
                y = a;
            });
    
            threadA.start();
            threadB.start();
    
            threadA.join();
            threadB.join();
    
            org.junit.jupiter.api.Assertions.assertFalse(x == 0 && y == 0);
        }
    
    }
    

    Results

    I ran the test until it fails several times. The results are as follows:

    InstructionReorderingTest.test [*] (12s 222ms): 29144 total, 1 failed, 29143 passed.
    InstructionReorderingTest.test [*] (26s 678ms): 69513 total, 1 failed, 69512 passed.
    InstructionReorderingTest.test [*] (12s 161ms): 27878 total, 1 failed, 27877 passed.
    

    Explanation

    The results we expect are

    • x = 0, y = 1: threadA runs to completion before threadB starts.
    • x = 1, y = 0: threadB runs to completion before threadA starts.
    • x = 1, y = 1: their instructions are interleaved.

    No one can expect x = 0, y = 0, which may happen as the test results showed.

    The actions in each thread have no dataflow dependence on each other, and accordingly can be executed out of order. (Even if they are executed in order, the timing by which caches are flushed to main memory can make it appear, from the perspective of threadB, that the assignments in threadA occurred in the opposite order.)

    Java Concurrency in Practice, Brian Goetz

提交回复
热议问题