寄存器中的内存最小速度最快,硬盘容量最大,速度最小,cup的第三级缓存是共享内存。
对于一个在同一行的数据XY,会被同时加载进CPU,这个现象叫cache line缓存行对齐, 如果左边的CPU核心加载了X并进行修改,但是此时并没有将数据写回进主内存,或者是第三级缓存,此时右边的CPU核心将X读进,并修改,此时就会产生数据不一致的情况。对于左边修改了数据右边如何才能知道,这是硬件层级需要解决的。 多线程一致性的硬件支持有一下集中方式。
锁总线的方式。总线锁会锁住bus总线,使得其他CPU不能访问内存中的其他地址,因而效率极低。CPU的共享内存都是通过
MESI(英特尔CPU) 等等之类的缓存一致性协议,相对于总线锁的方式MESI的性能好很多。
在特定情况下CPU会进行指令重排,以保证高效的执行。CPU如何保证特定的情况下不不乱序执行。通过内存屏障来保证指令的有序性。
下面是三种CPU指令内存屏障指令。
sfence:在sfence指令前的写操作必须在sfence后写操作完成之前完成操作。即在两次写操作之间加个屏障使其不能被重排。
lfence:在lfence指令前的读操作必须在lfence后的读操作完成之前完成操作。即在两次读操作之间加个屏障使其不能被重排。
mfence:在mfence指令前的读写操作必须在mfence的读写操作完成之前完成操作。即在一次读一次写和另一次读和一次写之间加一个屏障使其不能被重排。
CPU保证有序执行除了可以使用mfence,还可以使用
jvm内存屏障,对上面的CPU内存屏障进行组合,有如下四种屏障
jvms 2.4 2.5
Each Java Virtual Machine thread has its own pc (program counter) register.
每个Java虚拟机线程都有自己的程序计数器的存储空间。
At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method for that thread.
在任何时候,每个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法。
If that method is not native , the pc register contains the address of the Java Virtual Machine instruction currently being executed.
如果该方法不是本机方法,则pc寄存器包含当前正在执行的Java虚拟机指令的地址。
存放指令位置
虚拟机的运行,类似于这样的循环:
取PC中的位置,找到对应位置的指令;
执行该指令;
PC ++;
复制代码
JVM Stack
Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.
每个Java虚拟机线程都有一个私有Java虚拟机堆栈,与该线程同时创建。
A Java Virtual Machine stack stores frames
每个Java虚拟机存储的都是栈帧
Heap
The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads.
java 虚拟机有个所有线程共享的堆内存。
The heap is the run-time data area from which memory for all class instances and arrays is allocated.
堆是运行时数据区,从中分配所有类实例和数组的内存。
Method Area
The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads.
Java虚拟机具有一个在所有Java虚拟机线程之间共享的方法区域。
It stores per-class structures
存储每个类的结构
A run-time constant pool is a per-class or per-interface run-time representation of the constant_ pool table ina class file
An implementation of the Java Virtual Machine may use conventional stacks called native method stacks
JVM可以直接访问的内核空间的内存 (OS 管理的内存)
NIO , 提高效率,实现zero copy
上面的内容总结起来就是下面这张图
每个线程都有自己的栈内存,里面存放的是栈帧,如果有调用native方法就还存在native method stack,还有自己program counter程序计数器,用来记录每条指令的执行,当CPU切换线程的时候方便知道之前线程执行到哪条指令,所有线程共享堆内存和方法区,方法区有两种实现,在jdk8之前方法区叫PermGen永久代,jdk8及其以后的版本都叫Meta Space 元数据区。
栈帧:A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.
栈帧是用来存储数据部分结果,和执行动态链接,返回方法的值和处理异常调度。
我们看一下一个简单的方法的执行过程的栈帧是怎么样的。
pubilc class Test1{
pubilc static void main(String [] args){
Test h = new Test();
h.m1();
}
}
pubilc class Test{
public void m1(){
int i = 200;
}
}
复制代码
编译后的Test1字节码为:
0 new #2
3 dup
4 invokespcial #3
7 istore_1
8 iload_1
9 invokespcial #3
12 return
复制代码
对应Test字节码为:
0 ipush 200
3 istore_1
4 return
复制代码
我我们看一下执行过程,在含有主方法的字节码中,首先执行一个new指令。new一个对象的话,包括三个操作:
我们看上面指令,在这条 invokespcial #3