首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java并发性

Java并发性
EN

Stack Overflow用户
提问于 2015-06-23 20:43:29
回答 2查看 99关注 0票数 0

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

代码语言:javascript
复制
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%确定第二个线程是否会缓存变量,但在大多数情况下,它会这样做。我想我错过了一些很重要的东西。提前谢谢。

EN

回答 2

Stack Overflow用户

发布于 2015-06-23 20:46:51

根据Java内存模型,不能保证一个线程更改的值在另一个线程中是可见的。然而,它并没有说相反的话:它可以是可见的。这取决于虚拟机和硬件的实现。如果它现在在你的CPU和你的虚拟机上是可见的,这并不意味着它将永远在每个硬件和每个虚拟机上都可见。你不能依赖这一点。

如果您还想看到效果,可以将第二个线程代码替换为以下代码:

代码语言:javascript
复制
new Thread(new Runnable() {

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

这将在HotSpot虚拟机上产生稳定的结果:您的程序永远不会结束(尽管在number字段中添加volatile关键字将使其在5秒内结束)。当然,您也不能依赖这一点。

票数 8
EN

Stack Overflow用户

发布于 2015-06-23 20:47:47

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

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31003142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档