多线程几个有趣案例分析

多线程几个有趣案例分析

主线程开子线程

	boolean flag=true;
    public static void main(String[] args) throws InterruptedException {
        TestThread t = new TestThread();
        t.start();//开子线程 1
        t.flag = false;//主线程继续跑 2
        //绝大部分情况下都是2先执行,所以下面的输出语句不会执行
    }
    private void start() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(flag){
               		 System.out.println("sub thread");
                }
            }
        }).start();
    }

JIT激进优化产生的可见性问题

	boolean flag=true;
    public static void main(String[] args) throws InterruptedException {
        TestThread t = new TestThread();
        t.start();//开子线程 1
        Thread.sleep(1000);
        t.flag = false;//主线程继续跑 2
        //绝大部分情况下都是2先执行,所以下面的输出语句不会执行
    }
    private void start() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(flag){
               		 System.out.println("sub thread");
                }
            }
        }).start();
    }

在休眠1s后再把flag置为false;结果是程序打印了1s的sub Thread,这一点符合我们的正常逻辑。
重点来了,如果我们把 System.out.println(“sub thread”);这条语句删除,那么这段程序永远不会停止。
这就令人很费解

见下面的程序

	boolean flag=true;
    public static void main(String[] args) throws InterruptedException {
        TestThread t = new TestThread();
        t.start();//开子线程 1
        Thread.sleep(1000);
        t.flag = false;//主线程继续跑 2
        //绝大部分情况下都是2先执行,所以下面的输出语句不会执行
    }
    private void start() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(flag){
               		 //空轮询,永远不会停止
                }
            }
        }).start();
    }

问题分析:既然一直空轮询,那么可以确定的是子线程的flag一直是true,即使主线程已经修改为false。
什么原因导致flag一直是true,我先列举了一系列可能的原因如下:
原因一:主线程的flag对子线程不可见,加volatile关键字解决。
这个原因可以排除掉,就算我们的flag不是volatile的,但是总有一个时刻子线程会发现flag被改为flase了吧,不可能一直发现不了啊!并且加了打印语句1s过后程序停止,说明绝不是这个原因。
原因二:JVM晚期优化?
对于上面的空轮询,他认为是可以优化的,类似优化成下面的样子:
把flag暂存起来,这样就不用每次都去堆里面找。这样temp就一直都是true。

	private void start() {
        new Thread(new Runnable() {
        boolean temp = flag;
            @Override
            public void run() {
                while(temp){
               		 //空轮询,永远不会停止
                }
            }
        }).start();
    }

而对于再while里面加了打印语句(打印也是方法调用)或者一些方法调用JIT不敢做优化。
上面这些我不敢保证绝对正确,毕竟我不知道怎么可以验证JIT确实对我的空轮询做了晚期优化,这些都只是猜测。
深入理解java虚拟机11章节 深入讲了JIT晚期优化,看的很晕,毕竟基本纯理论,很难验证。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值