【Java】分享一个诡异的可见性问题

在这里插入图片描述

1.概述

转载:http://www.javastack.cn/article/2017/share-the-visibility-of-a-strange-question/

之前介绍过可见性的特性,最近做测试的时候发现了一个很诡异的问题,下面看看这三个例子。

test1:

   private static volatile  int n1 = 0;
    private static   int n2 = 0;

    @Test
    public void volatileTest(){
        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                n1 = 1;
            }
        }.start();

        while (n1 == 0){

        }

        System.out.println("test 1 end");
    }

test1这个例子加了volatile,所以程序正确退出输出test1 end

test2:

@Test
    public void volatileTest1(){
        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                n2 = 1;
            }
        }.start();

        while (n2 == 0){
            System.out.println("n2");
        }

        System.out.println("test 2 end");
    }


    @Test
    public void volatileTest2(){
        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                n2 = 1;
            }
        }.start();

        while (n2 == 0){
            System.out.print("n3");
        }

        System.out.println("test 3 end");
    }


test2这个例子没有加volatile,程序也正常退出并输出一堆0并输出了test2 end,这是为什么呢?没有加volatile为什么也有可见性?看起来是很诡异的问题,问题是在while里面加了一行System…输出问题,打开源码看println方法里面加了synchronized同步块,正是因为这个同步块保证了里面变量x的可见性,这个诡异的问题也就解开了。

test3:

   @Test
    public void volatileTest3(){
        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                n2 = 1;
            }
        }.start();

        while (n2 == 0){
        }

        System.out.println("test 3 end");
    }

test3这个例子即没加volatile,也没有在while里面加System…输出语句,所以线程对变量n3的修改对主线程不可见,程序一直循环,没有输出结果。

猜你喜欢

转载自blog.csdn.net/qq_21383435/article/details/108446496