Java instructions to reorder test classes

Summarized the two instruction rearrangement scenarios and wrote code to implement them.
Scenario 1: Two threads assign values ​​back and forth to different variables to verify whether instruction re-arrangement occurs. Scenario 2:
Singleton mode is a lazy mode. DCL+volatile can ensure that no accidents occur, but volatile is not added here intentionally to verify whether instruction re-arrangement occurs. Platoon leads to unexpected situations

import org.junit.Test;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;

public class InstructReorderTest {
    
    

    int x = 0, y = 0, a = 0, b = 0;
    @Test
    public void test() throws Exception {
    
    
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        long start = System.nanoTime();
        for (long i = 0; i < Long.MAX_VALUE; i++) {
    
    
            x = y = a = b = 0;
            CountDownLatch latch = new CountDownLatch(2);
            Runnable r1 = () -> {
    
    a=1;x=b;latch.countDown();};
            Runnable r2 = () -> {
    
    b=1;y=a;latch.countDown();};
            // 当发生指令重排的时候,以上两行代码的ab与xy就可能交换了顺序. 如果xy同时=0则可证明以上两行代码同时发生了指令重排
            executorService.submit(r1);
            executorService.submit(r2);

            latch.await(1, TimeUnit.SECONDS);
            if (x + y == 0) {
    
    
                long end = System.nanoTime();
                System.err.println("x y 同时为0了. i: " + i + ", cost in ms: " + ((end - start) / 1_000_000));
                // x y 同时为0了. i: 25037, cost in ms: 692
                return;
            }
        }
    }

    // 验证单例中的指令重排
    // 没跑出来,执行了超过千万次,都没有发生预期的指令重排,重写了逻辑,92万次发生了预期的指令重排
    // o is null, i: '927155', cost: '34006'ms
    // o is null, i: '1612447', cost: '20890'ms
    // o is null, i: '1128129', cost: '16097'ms
    // o is null, i: '10873976', cost: '133588'ms
    // o is null, i: '15425452', cost: '204436'ms
    @Test
    public void test_singleton() throws ExecutionException, InterruptedException {
    
    
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        long s = System.currentTimeMillis();
        Callable r2 = () -> T.getInstance().o;
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
    
    
            T.t = null;
            List<Future> futures = new LinkedList<>();
            for (int j = 0; j < 2; j++) {
    
    
                futures.add(executorService.submit(r2));
            }
            for (Future future : futures) {
    
    
                if (null == future.get()) {
    
    
                    long e = System.currentTimeMillis();
                    System.out.printf("o is null, i: '%s', cost: '%s'ms\n", i, (e - s));
                    return;
                }
            }
            if (i % 10_0000 == 0) {
    
    
                System.out.println("i: " + i);
            }
        }

    }

    static class T {
    
    
        Object o;

        public T(Object o) {
    
    
            this.o = o;
        }

        static T t;
        static T getInstance() {
    
    
           if (null == t) {
    
    
               synchronized (T.class) {
    
    
                   if (null == t) {
    
    
                       t = new T(new Object());
                   }
               }
           }
           return t;
        }
    }
}

Guess you like

Origin blog.csdn.net/booynal/article/details/129115359