java 指令重排序测试

java中,synchronized和volatile都可以防止指令重排序,现在来验证一下其实际效果。

如下代码所示,进行测试1:两个线程,一个执行批量赋值操作,另外一个检测批量赋值操作是否乱序执行。

测试结果:确实会出现了乱序执行的情况。

/**
 * 指令重排序测试
 *
 * @author zhangxz
 * @date 2019-11-17 16:40
 */

public class CmdReorderTest {

    private static int a = 0;
    private static int b = 0;
    private static int c = 0;
    private static int d = 0;
    private static int e = 0;
    private static int f = 0;
    private static int g = 0;
    private static int h = 0;

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 500000; i++) {
            //join可以保证线程a b都执行完成之后,再继续下一次循环
            ThreadA threadA = new ThreadA();
            threadA.start();

            ThreadB threadB = new ThreadB();
            threadB.start();

            threadA.join();
            threadB.join();

            //清空数据,便于测试
            a = 0;
            b = 0;
            c = 0;
            d = 0;
            e = 0;
            f = 0;
            g = 0;
            h = 0;
        }
    }

    static class ThreadA extends Thread {
        @Override
        public void run() {
            a = 1;
            b = 1;
            c = 1;
            d = 1;
            e = 1;
            f = 1;
            g = 1;
            h = 1;
        }
    }

    static class ThreadB extends Thread {
        @Override
        public void run() {
            if (b == 1 && a == 0) {
                System.out.println("b=1");
            }
            if (c == 1 && (a == 0 || b == 0)) {
                System.out.println("c=1");
            }
            if (d == 1 && (a == 0 || b == 0 || c == 0)) {
                System.out.println("d=1");
            }
            if (e == 1 && (a == 0 || b == 0 || c == 0 || d == 0)) {
                System.out.println("e=1");
            }
            if (f == 1 && (a == 0 || b == 0 || c == 0 || d == 0 || e == 0)) {
                System.out.println("f=1");
            }
            if (g == 1 && (a == 0 || b == 0 || c == 0 || d == 0 || e == 0 || f == 0)) {
                System.out.println("g=1");
            }
            if (h == 1 && (a == 0 || b == 0 || c == 0 || d == 0 || e == 0 || f == 0 || g == 0)) {
                System.out.println("h=1");
            }
        }
    }

}

测试2:把上面代码的所有静态变量,都使用volatile修饰

测试结果:不再出现有乱序执行的结果,可以推测是volatile保证了指令执行的有序性,不会被重排序。

如下代码所示,进行测试3:在上面的批量赋值操作,以及批量检测操作,两个操作,都加上锁,比如ReentrantLock,或者synchronized

测试结果:不再出现有乱序执行的结果,可以推测加锁,也可以保证指令执行的有序性。其实这个可以理解为互斥访问的特性,保证了有序性。

/**
 * 指令重排序测试
 *
 * @author zhangxz
 * @date 2019-11-17 16:40
 */

public class CmdReorderTest {

    private static int a = 0;
    private static int b = 0;
    private static int c = 0;
    private static int d = 0;
    private static int e = 0;
    private static int f = 0;
    private static int g = 0;
    private static int h = 0;

/*
    private static volatile int a = 0;
    private static volatile int b = 0;
    private static volatile int c = 0;
    private static volatile int d = 0;
    private static volatile int e = 0;
    private static volatile int f = 0;
    private static volatile int g = 0;
    private static volatile int h = 0;
*/

    private static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 500000; i++) {
            //join可以保证线程a b都执行完成之后,再继续下一次循环
            ThreadA threadA = new ThreadA();
            threadA.start();

            ThreadB threadB = new ThreadB();
            threadB.start();

            threadA.join();
            threadB.join();

            //清空数据,便于测试
            a = 0;
            b = 0;
            c = 0;
            d = 0;
            e = 0;
            f = 0;
            g = 0;
            h = 0;
        }
    }

    static class ThreadA extends Thread {
        @Override
        public void run() {
            lock.lock();
            try {
                a = 1;
                b = 1;
                c = 1;
                d = 1;
                e = 1;
                f = 1;
                g = 1;
                h = 1;
            } finally {
                lock.unlock();
            }
        }
    }

    static class ThreadB extends Thread {
        @Override
        public void run() {
            lock.lock();
            try {
                if (b == 1 && a == 0) {
                    System.out.println("b=1");
                }
                if (c == 1 && (a == 0 || b == 0)) {
                    System.out.println("c=1");
                }
                if (d == 1 && (a == 0 || b == 0 || c == 0)) {
                    System.out.println("d=1");
                }
                if (e == 1 && (a == 0 || b == 0 || c == 0 || d == 0)) {
                    System.out.println("e=1");
                }
                if (f == 1 && (a == 0 || b == 0 || c == 0 || d == 0 || e == 0)) {
                    System.out.println("f=1");
                }
                if (g == 1 && (a == 0 || b == 0 || c == 0 || d == 0 || e == 0 || f == 0)) {
                    System.out.println("g=1");
                }
                if (h == 1 && (a == 0 || b == 0 || c == 0 || d == 0 || e == 0 || f == 0 || g == 0)) {
                    System.out.println("h=1");
                }
            } finally {
                lock.unlock();
            }
        }
    }

}
原文地址:https://www.cnblogs.com/zhangxuezhi/p/11885519.html