Java内存模型指定了JVM和计算机内存是如何进行协作
Java内存模型的原理
Java内存被分为线程栈和堆
栈:JVM中的每个线程拥有一个自己的线程栈,线程栈中包含当前调用方法的信息,所有被调用方法的本地变量。
堆:java应用程序中的所有对象,与线程无关。
- 局部变量==>栈==>线程安全
- 局部对象==>引用在栈,对象在堆==>可能安全
- 对象方法里面的局部变量==>对象在堆,局部变量在栈==>线程安全
- 对象里面的成员变量==>堆==>线程不安全
- 静态类==>堆==>线程不安全
public class MyRunnable implements Runnable() {
public void run() {
methodOne();
}
public void methodOne() {
int localVariable1 = 45;
MySharedObject localVariable2 =
MySharedObject.sharedInstance;
//... do more with local variables.
methodTwo();
}
public void methodTwo() {
Integer localVariable1 = new Integer(99);
//... do more with local variable.
}
}
public class MySharedObject {
//static variable pointing to instance of MySharedObject
public static final MySharedObject sharedInstance =
new MySharedObject();
//member variables pointing to two objects on the heap
public Integer object2 = new Integer(22);
public Integer object4 = new Integer(44);
public long member1 = 12345;
public long member1 = 67890;
}
硬件内存架构
- 一个现代计算机通常由两个或者多个CPU。其中一些CPU还有多核。
- 每个CPU都包含一系列的寄存器,它们是CPU内存的基础。
- 每个CPU可能还有一个CPU缓存层。CPU访问缓存层的速度快于访问主存的速度,但通常比访问内部寄存器的速度还要慢一点。
- 一个计算机还包含一个主存。所有的CPU都可以访问主存。主存通常比CPU中的缓存大得多。
- 通常情况下,当一个CPU需要读取主存时,它会将主存的部分读到CPU缓存中。它甚至可能将缓存中的部分内容读到它的内部寄存器中,然后在寄存器中执行操作。当CPU需要将结果写回到主存中去时,它会将内部寄存器的值刷新到缓存中,然后在某个时间点将值刷新回主存。
Java内存模型和硬件内存架构之间的桥接
共享对象的可见性
如果两个或者更多的线程在没有正确的使用volatile声明或者同步的情况下共享一个对象,一个线程更新这个共享对象可能对其它线程来说是不接见的。
可以使用volatile关键字解决这个问题
race condition
如果两个或者更多的线程共享一个对象,多个线程在这个共享对象上更新变量,就有可能发生race conditions。
可以使用同步块解决这个问题