如果你想设计表现良好的并发程序,理解Java内存模型是非常重要的。Java内存模型规定了如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。
1 Java内存模型
我们先来看看Java 线程运行内存示意图,如下图所示:

Java 线程运行内存示意图
这张图告诉我们在线程运行的时候有一个内存专用的一小块内存,当Java程序会将变量同步到线程所在的内存,这时候会操作工作内存中的变量,而线程中变量的值何时同步回主内存是不可预期的。
因此,依据上面图的线程运行内存示意图,Java内存模型在JVM内部抽象划分为线程栈和堆。如下图所示:

JMM划分为线程栈和堆
1.1 线程栈与堆
每一个运行在Java虚拟机里的线程都拥有自己的线程栈。这个线程栈包含了 线程调用的方法当前执行点相关的信息,同时线程栈具有如下特性:
一个线程仅能访问自己的线程栈; 一个线程创建的本地变量对其它线程不可见,仅自己可见;
即使两个线程执行同样的代码,这两个线程任然在在自己的线程栈中的代码来创建本地变量。因此,每个线程拥有每个本地变量的独有版本。
所有原始类型的本地变量都存放在线程栈上,因此对其它线程不可见。一个线程可能向另一个线程传递一个原始类型变量的拷贝,但是它不能共享这个原始类型变量自身。
堆上包含在Java程序中创建的所有对象,无论是哪一个对象创建的。这包括原始类型的对象版本。如果一个对象被创建然后赋值给一个局部变量,或者用来作为另一个对象的成员变量,这个对象任然是存放在堆上。
所以,调用栈和本地变量存放在线程栈上,对象存放在堆上,如下图所示:

线程栈与堆 & 变量、对象、调用栈
一个本地变量可能是原始类型,在这种情况下,它总是“呆在”线程栈上; 一个本地变量也可能是指向一个对象的一个引用。在这种情况下,引用(这个本地变量)存放在线程栈上,但是对象本身存放在堆上; 一个对象可能包含方法,这些方法可能包含本地变量。这些本地变量任然存放在线程栈上,即使这些方法所属的对象存放在堆上。 一个对象的成员变量可能随着这个对象自身存放在堆上。不管这个成员变量是原始类型还是引用类型。 静态成员变量跟随着类定义一起也存放在堆上。
存放在堆上的对象可以被所有持有对这个对象引用的线程访问。当一个线程可以访问一个对象时,它也可以访问这个对象的成员变量。如果两个线程同时调用同一个对象上的同一个方法,它们将会都访问这个对象的成员变量,但是每一个线程都拥有这个本地变量的私有拷贝。
上面说到的几点,如下图所示:

栈、堆 & 本地变量、静态变量
1 Java内存模型
我们先来看看Java 线程运行内存示意图,如下图所示:

Java 线程运行内存示意图
这张图告诉我们在线程运行的时候有一个内存专用的一小块内存,当Java程序会将变量同步到线程所在的内存,这时候会操作工作内存中的变量,而线程中变量的值何时同步回主内存是不可预期的。
因此,依据上面图的线程运行内存示意图,Java内存模型在JVM内部抽象划分为线程栈和堆。如下图所示:

JMM划分为线程栈和堆
1.1 线程栈与堆
每一个运行在Java虚拟机里的线程都拥有自己的线程栈。这个线程栈包含了 线程调用的方法当前执行点相关的信息,同时线程栈具有如下特性:
一个线程仅能访问自己的线程栈; 一个线程创建的本地变量对其它线程不可见,仅自己可见;
即使两个线程执行同样的代码,这两个线程任然在在自己的线程栈中的代码来创建本地变量。因此,每个线程拥有每个本地变量的独有版本。
所有原始类型的本地变量都存放在线程栈上,因此对其它线程不可见。一个线程可能向另一个线程传递一个原始类型变量的拷贝,但是它不能共享这个原始类型变量自身。
堆上包含在Java程序中创建的所有对象,无论是哪一个对象创建的。这包括原始类型的对象版本。如果一个对象被创建然后赋值给一个局部变量,或者用来作为另一个对象的成员变量,这个对象任然是存放在堆上。
所以,调用栈和本地变量存放在线程栈上,对象存放在堆上,如下图所示:

线程栈与堆 & 变量、对象、调用栈
一个本地变量可能是原始类型,在这种情况下,它总是“呆在”线程栈上; 一个本地变量也可能是指向一个对象的一个引用。在这种情况下,引用(这个本地变量)存放在线程栈上,但是对象本身存放在堆上; 一个对象可能包含方法,这些方法可能包含本地变量。这些本地变量任然存放在线程栈上,即使这些方法所属的对象存放在堆上。 一个对象的成员变量可能随着这个对象自身存放在堆上。不管这个成员变量是原始类型还是引用类型。 静态成员变量跟随着类定义一起也存放在堆上。
存放在堆上的对象可以被所有持有对这个对象引用的线程访问。当一个线程可以访问一个对象时,它也可以访问这个对象的成员变量。如果两个线程同时调用同一个对象上的同一个方法,它们将会都访问这个对象的成员变量,但是每一个线程都拥有这个本地变量的私有拷贝。
上面说到的几点,如下图所示:

栈、堆 & 本地变量、静态变量













