public class Demo {
static int money = 10000;
public static void main(String[] args) {
new Girl().start();
new Boy().start();
}
}
class Boy extends Thread {
@Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Demo.money = 90000;
}
}
class Girl extends Thread {
@Override
public void run() {
while (Demo.money == 10000) {
}
System.out.println("财产发生变化");
}
}
这段代码中money变量在线程中发生变化,但是Girl却没有停止循环、输出内容
分析一下
在java的内存模型中堆内存是唯一的,栈内存是线程独有的,也就是说每一个线程都有自己的线程栈,所以在上面的代码中我们在堆里面创建了一个money的共享数据,boy和girl两个线程将这个moeny在自己的线程栈中临时存储称之为变量副本,这个时候boy修改money是先修改的变量副本然后再修改的堆内的共享数据,而girl还在使用的变量副本是变更前存储的,并不是最新的。
小结
堆内存是唯一的,每一个线程都有自己的线程栈
每一个线程在使用堆里面的变量时,会先拷贝一份到线程栈中
在线程中,每一次使用变量是从栈内获取的
volatile
/**
* 强制线程每一次在使用变量的时候都会去堆内获取最新值
*/
volatile static int money = 10000;
当然我们也可以使用synchronized来解决这个问题
因为synchronized代码块在运行的时候
会先清空变量副本,拷贝最新的值到变量副本中