一、 问题
先看一个例子:
public class Counter {
public static int count = 0;
public static void inc() {
count++;
}
public static void main(String[] args) {
// 同时启动1000个线程,去进行i++计算,看看实际结果
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Counter.inc();
}
}).start();
}
// 这里每次运行的值都有可能不同,可能为1000
System.out.println("运行结果:Counter.count=" + Counter.count);
}
}
运行结果:
第一次:
运行结果:Counter.count=972
第二次:
运行结果:Counter.count=973
第三次:
运行结果:Counter.count=993
会发现每次运行结果都不一样。
二、原因
在JVM运行时,有一块内存区域用作JVM虚拟机栈。每一个线程都拥有一个线程栈,里边保存了线程的变量信息。当线程访问一个对象的时候,会通过对象的引用回去到对象在堆内存中的值,并复制到线程本地内存中。之后线程会操作这个对象副本,不会直接操作对象本身。在线程结束的时候,会把副本的值写回堆内存中。如下图所示: