1. JVM内存结构、Java内存模型与Java对象模型 辨析
1.1 JVM内存结构
-
JVM内存结构详解请看:认识JVM的内存布局和运行时数据区
-
JVM内存结构,也可以称作JVM运行时内存,这个和我们代码执行在JVM上使用内存有关。
1.2 Java内存模型
- Java内存模型则是和并发编程相关。后面会仔细说明
1.3 Java对象模型
- Java对象模型是指Java对象在虚拟机中的表现形式。
- Java对象模型是对象自身的存储结构
- JVM会给类创建一个
instanceKlass
保存着方法区,用在JVM层表示这个Java类 - 当我们在代码中使用new创建一个对象时,JVM会创建一个instanceOopDesc对象,这个对象包含了对象头和实例数据。
2. Java内存模型(JMM)解析
- Java内存模型,(JMM,Java Memory Model)实际上是一组JVM的规范。以便可以统一利用这些规范,更方便得开发多线程程序
2.1 重排序
- 重排序案例
/**
* 重排序示例
* @author yiren
*/
public class OutOfOrderExecution {
private static int x = 0, y = 0;
private static int a = 0, b = 0;
public static void main(String[] args) throws InterruptedException {
Thread one = new Thread(() -> {
a = 1;
x = b;
});
Thread two = new Thread(() -> {
b = 1;
y = a;
});
one.start();
two.start();
one.join();
two.join();
System.out.println("x=" + x + ", y=" + y);
}
}
- 我们可以想到产生的几种情况:
- a=1; x=b; b=1; y=a -> 结果:x=0,y=1
- b=1; y=a; a=1; x=b -> 结果:x=1,y=0
- b=1; a=1; x=b; y=a -> 结果:x=1,y=1
- 第三种情况比较难出现,我们改造一下代码
/**
* 重排序示例
*
* @author yiren
*/
public class OutOfOrderExecution {
private static int x = 0, y = 0;
private static int a = 0, b = 0;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; x == 0 || y == 0; i++) {
x = 0;
y = 0;
a = 0;
b = 0;
CountDownLatch countDownLatch = new CountDownLatch(1);
Thread one = new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
a = 1;
x = b;
});
Thread two = new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
b = 1;
y = a;
});
one.start();
two.start();
countDownLatch.countDown();
one.join();
two.join();
System.out.println("i=" + i + ", x=" + x + ", y=" + y);
}
}
}
...
i=147267, x=0, y=1
i=147268, x=0, y=1
i=147269, x=0, y=1
i=147270, x=0, y=1
i=147271, x=1, y=1
Process finished with exit code 0
- 另外还有不容易想到的情况:也就是重排序的情况!x=0 y=0 我们修改下代码,将main函数前面代码改成如下:
public static void main(String[] args) throws InterruptedException {
x = 1;
for (int i = 0; x != 0 || y != 0; i++) {
x = 0;
....
复制代码
...
i=557, x=1, y=0
i=558, x=0, y=1
i=559, x=1, y=0
i=560, x=1, y=0
i=561, x=0, y=0
Process finished with exit code 0
复制代码
- 如上:结果我们发现出现了x=0,y=0,为什么会出现这种情况呢?
- 也就是我们程序在执行的时候 b=1和y=a 、a=1和x=b重排序了,也就是交换了执行顺序。在面试中被问到并发知识的时候,大多都会被问到“请你说一下自己对于AQS原理的理解”。下面给大家一个示例供大家参加,面试不是背题,大家一定要假如自己的思想,即使加入不了自己的思想也要保证自己能够通俗的讲出来而不是背出来。在此我向大家推荐一个架构学习交流圈。交流学习伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多