我有以下问题:为什么在这种情况下,第二个线程会看到第一个线程更改了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%确定第二个线程是否会缓存变量,但在大多数情况下,它会这样做。我想我错过了一些很重要的东西。提前谢谢。
发布于 2015-06-23 20:46:51
根据Java内存模型,不能保证一个线程更改的值在另一个线程中是可见的。然而,它并没有说相反的话:它可以是可见的。这取决于虚拟机和硬件的实现。如果它现在在你的CPU和你的虚拟机上是可见的,这并不意味着它将永远在每个硬件和每个虚拟机上都可见。你不能依赖这一点。
如果您还想看到效果,可以将第二个线程代码替换为以下代码:
new Thread(new Runnable() {
@Override
public void run() {
while (number < 100) {
}
System.out.println(number);
}
}).start();这将在HotSpot虚拟机上产生稳定的结果:您的程序永远不会结束(尽管在number字段中添加volatile关键字将使其在5秒内结束)。当然,您也不能依赖这一点。
发布于 2015-06-23 20:47:47
这就是所谓的“共享内存”。
变量"number“在两个线程(堆)共享的内存中,而不是在每个线程堆栈上。
这就是为什么在一个线程中更改它会在另一个线程中反映出来。
https://stackoverflow.com/questions/31003142
复制相似问题