volatile修饰数组

结论:volatile修饰对象或数组时,只能保证他们的引用地址的可见性。

非volatile数组的可见性问题

public class Test {
    static int[] a = new int[]{1};

    public static void main(String[] args) {
        new Thread(() -> {  //线程A
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a[0] = 0;
        }).start();

        new Thread(()-> {   //线程B
            try {
                while (true) {
                    if (a[0] == 0) {
                        System.out.println("结束");
                        break;
                    }
                    //Thread.sleep(10);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

}

由此可见打印不出来‘’结束‘’
volatile修饰数组_第1张图片
volatile数组的可见性问题

public class Test {
    static volatile int[] a = new int[]{1};

    public static void main(String[] args) {
        new Thread(() -> {  //线程A
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a[0] = 0;
        }).start();

        new Thread(()-> {   //线程B
            try {
                while (true) {
                    if (a[0] == 0) {
                        System.out.println("结束");
                        break;
                    }
                    //Thread.sleep(10);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

}

volatile修饰数组_第2张图片
发现结果和我们预期的相反
当ThreadB读取array时,因为array的引用被volatile修饰,所以ThreadB对所有变量都会从主内存去获取,当然也就包括array[0]。
在这里插入图片描述
https://stackoverflow.com/questions/53753792/java-volatile-array-my-test-results-do-not-match-the-expectations

其实如果不给数组加volatile就永远不会打印“结束”,这种绝对的认为是错误的,volatile保证了其变量及时可见性而不会引起线程安全的问题,就算不加volatile,cpu在空闲的时候也会将array[0]的值从线程缓存刷新到主存,只是while(true)太快了,导致cpu一直没空。我们可以使用Thread.sleep(10)让出CPU让其有空将线程变量刷新到主内存中去。记得先去掉volatile修饰

public class Test {
    static  int[] a = new int[]{1};

    public static void main(String[] args) {
        new Thread(() -> {  //线程A
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a[0] = 0;
        }).start();

        new Thread(()-> {   //线程B
            try {
                while (true) {
                    if (a[0] == 0) {
                        System.out.println("结束");
                        break;
                    }
                    Thread.sleep(10);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

}

你可能感兴趣的:(java,java,jvm,开发语言)