while循环使用print输出为什么会结束死循环?

  • Post author:
  • Post category:其他


话不多说,先上代码

class Hero{
    int num = 0;
    public void addNum(){
        this.num = 100;
    }
}
public class VolatileTest {
    public static void main(String[] args) {
        Hero hero = new Hero();
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"mission start...");
            //睡眠3秒
            try {
                TimeUnit.SECONDS.sleep(3);
                hero.addNum();
                System.out.println(Thread.currentThread().getName()+"update mission :update my num:"+hero.num);
            } catch (InterruptedException e) {
                System.out.println(e.getMessage());
            }
        },"AAA").start();
        //第二个线程,main线程,(理想情况下,上面调用过addNum后,num=100,就不会执行while循环
        while(hero.num==0){
           System.out.println("我是天才");
        }
        System.out.println(Thread.currentThread().getName()+"  mission success...miannum"+hero.num);
    }
}

写这段程序的原本目的是为了测试jvm提供的轻量级的同步机制–volatile的性质:


1.保证可见性

2.不保证原子性

3.禁止指令重排


在写代码的时候为了满足自己,将while循环体加上了print输出语句;

原本预想的结果是:不加volatile修饰,无法保证可见性,num ==0,while循环一直输出“

我是天才

”,可结果是,线程sleep三秒后,就输出了“mission over”任务结束;

这中间到底发生了如何诡异的事情,有什么不可告人的秘密,让我们重新回到那个令人疑惑的代码块上

 while(hero.num==0){
           System.out.println("我是天才");
        }

为了进一步探究如何发生这般诡异离奇,令人疑惑的事情,我决定不畏艰险,放手一搏,于是乎,左手Ctrl右手鼠标左键,进入了println这个诡异的地方:

   public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

哦豁,是不是有种“初极狭,才通人。复行数十步,豁然开朗”的感觉,想必大家看到这里就明白了,其实并没有什么诡异莫测,匪夷所思,怪诞诡奇的地方,有的只是

一个synchronized同步代码块,在我们使用prinln的时候,会在底层进入synchronized代码块,这期间,就会和主内存的变量保持一致,从而也实现了可见性

。看到了结果,是不是觉得很简单。



从这件事上,我们知道,任何事情,不论看起来如何诡异,只要怀揣着一颗发现的心,深入探究,问题有时其实很简单。



版权声明:本文为beArrow原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。