JVM 运行时数据区与JMM 内存模型攻略
1. JVM 运行时数据区
JVM(Java虚拟机)运行时数据区是指在Java程序执行期间,用于存储数据和执行指令的内存区域。JVM运行时数据区主要包括以下几个部分:
1.1 方法区(Method Area)
方法区用于存储类的结构信息,包括类的字段、方法、构造函数、接口等。方法区是被所有线程共享的内存区域。
示例说明:
public class MyClass {
private static final int MAX_VALUE = 100;
private String name;
public void printName() {
System.out.println(name);
}
}
在上面的示例中,MyClass
类的结构信息,包括字段MAX_VALUE
和name
,以及方法printName()
,都会被存储在方法区中。
1.2 堆(Heap)
堆是用于存储对象实例的内存区域。所有通过new
关键字创建的对象都会被分配到堆中。堆是被所有线程共享的内存区域。
示例说明:
public class Main {
public static void main(String[] args) {
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
}
}
在上面的示例中,obj1
和obj2
是通过new
关键字创建的MyClass
对象,它们会被分配到堆中。
1.3 栈(Stack)
栈用于存储方法的局部变量、方法参数和方法调用的状态。每个线程都有自己的栈,栈中的数据是私有的,其他线程无法访问。
示例说明:
public class Main {
public static void main(String[] args) {
int a = 10;
int b = 20;
int sum = add(a, b);
System.out.println(sum);
}
public static int add(int x, int y) {
return x + y;
}
}
在上面的示例中,main
方法中的局部变量a
、b
和sum
,以及add
方法中的参数x
和y
,都会被存储在栈中。
1.4 程序计数器(Program Counter Register)
程序计数器用于存储当前线程正在执行的字节码指令的地址。每个线程都有自己的程序计数器,它是线程私有的。
示例说明:
public class Main {
public static void main(String[] args) {
int a = 10;
int b = 20;
int sum = add(a, b);
System.out.println(sum);
}
public static int add(int x, int y) {
int result = x + y;
return result;
}
}
在上面的示例中,程序计数器会记录当前线程执行到哪条字节码指令。
2. JMM 内存模型
JMM(Java内存模型)定义了Java程序中多线程并发访问共享内存的规则。JMM确保多线程之间的内存可见性和操作的原子性。
2.1 主内存(Main Memory)
主内存是所有线程共享的内存区域,用于存储所有的变量和对象实例。
示例说明:
public class Main {
private static int counter = 0;
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter++;
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter++;
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter);
}
}
在上面的示例中,counter
变量是共享的,两个线程分别对其进行自增操作。由于线程之间的操作不是原子的,可能会导致最终输出的结果不是预期的2000。
2.2 工作内存(Working Memory)
工作内存是每个线程私有的内存区域,用于存储主内存中的变量副本。线程在执行时,会将主内存中的变量复制到工作内存中进行操作。
示例说明:
public class Main {
private static int counter = 0;
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
synchronized (Main.class) {
counter++;
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
synchronized (Main.class) {
counter++;
}
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter);
}
}
在上面的示例中,通过synchronized
关键字保证了对counter
变量的操作是原子的,避免了并发访问导致的问题。
以上就是关于JVM运行时数据区与JMM内存模型的详细讲解,希望对你有帮助!
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JVM 运行时数据区与JMM 内存模型 - Python技术站