结论: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数组的可见性问题
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();
    }
}

 发现结果和我们预期的相反
 当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();
    }
}













![[ubuntu]ubuntu设置虚拟内存](https://img-blog.csdnimg.cn/f361ea3758bb4d9dab55d713413d60ca.jpeg)





