H5W3
当前位置:H5W3 > 其他技术问题 > 正文

java多线程中while循环的问题

public class Test{

    public static void main(String[] args) {
        try {
            MyThread th = new MyThread();
            th.start();
            Thread.sleep(1000);
            th.setter(false);
            System.out.println("已设为false");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class MyThread extends Thread {
    private boolean flag = true;

    public boolean getter() {
        return flag;
    }

    public void setter(boolean fl) {
        this.flag = fl;
    }

    public void run() {
        System.out.println("进入MyThread");
    
        while (flag == true){
        }

        System.out.println("Mythread结束:"+this.flag);
    }
}

上面的while循环,当main函数设置flag为false,循环体为空的话,后面的语句不会执行,会一直停留在那里;而在循环体中加上一句,比如System.out.println(),循环就会结束,后面的语句就会执行;并且在循环体中加入++i并打印,多次执行发现while结束的时候,i的值都不一样,说明不是正常结束循环。


  1. while循环体为空为什么不会退出循环,加入一句打印就会退出循环?

  2. 加入打印,循环应该也不是正常退出,此时是什么机制退出循环的?

回答:

因为多线程之间不是绝对同步的。
在运行时为了提高效率会将数据加载到寄存器中,所以有时虽然内存中数据已经改变,但还未即时更新到寄存器中,就会出现不同步的情况。
至于为什么空执行体迟迟不与内存数据同步,我猜测是访问flag频率过高,jvm的调度机制可能会选择在执行其他任务的时候同步flag,所以当你加了一句打印语句之后发现flag更新了。
所以你每次得到的递增值也是不同的。
volatile 关键字可以强制每次都从内存中读取,这样可以实现同步变量,但效率会低不少。

回答:

MyThread线程的flag是从其工作内存取,while语句调用太频繁意味着访问flag太频繁,导致主内存不会及时刷新工作内存的flag值(详细可了解JMM(Java memory Model)),所以一直会访问到flagfalse,当加入System.out.println()后,访问flag就会有明显间隔,主内存就会有空去刷新到MyThread线程的工作内存,这样才能正常退出while循环。
至于i的值不一样,这个是正常的,且不说Thread.sleep(1000)不能严格控制1秒的执行时间,就算时间一定,循环的次数也是未知的。

本文地址:H5W3 » java多线程中while循环的问题

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址