繁体   English   中英

Java并发

[英]Java concurrency

我有以下问题:为什么在这种情况下,第二个线程看到第一个线程何时更改number的值:

public static void main(String[] args) throws InterruptedException {

    Temp t = new Temp();
    t.go();
}

static class Temp {
    int number = 2;

    public void go() {

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                number = 100;
            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    System.out.println(number);
                }
            }
        }).start();
    }
}

我希望从第二个线程缓存数字值,并且当第一个线程更改它时,第二个线程对此将是“无知的”,并且它将始终打印2! 但是实际上,当第一个线程更改了数字变量时,第二个线程看到了这一更改并开始打印100。为什么呢? 我知道并不是100%确定第二个线程会缓存该变量,但是在大多数情况下,它会这样做。 我想我缺少重要的东西。 提前致谢。

根据Java内存模型,不能保证一个线程更改的值将从另一个线程可见。 但是,它并没有说明相反的含义:它是可见的。 这取决于虚拟机和硬件的实现。 如果今天可以在您的VM的CPU上看到它,则并不意味着它将始终在每个硬件和每个虚拟机上都可见。 您就是不能依靠它。

如果仍然希望看到效果,可以将第二个线程代码替换为以下代码:

new Thread(new Runnable() {

    @Override
    public void run() {
        while (number < 100) {
        }
        System.out.println(number);
    }
}).start();

这会在HotSpot虚拟机上产生稳定的结果:您的程序永无止境(尽管在number字段上添加volatile关键字将使其在5秒后结束)。 当然,您也不能依靠它。

这就是所谓的“共享内存”。

变量“ number”在两个线程(堆)共享的内存中,而不是在每个线程堆栈上。

这就是为什么在一个线程中更改它会在另一个线程上反映出来的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM