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

431 篇文章 485 订阅 ¥19.90 ¥99.00
本文通过三个示例探讨Java中关于可见性的奇怪现象,重点分析了未使用volatile但依然表现出可见性的原因,涉及println方法内部的synchronized同步块在确保变量可见性方面的作用。
摘要由CSDN通过智能技术生成

在这里插入图片描述

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的修改对主线程不可见,程序一直循环,没有输出结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值