关于Java中的内存屏障
如何打破双亲委派机制
继承ClassLoader类后重写loadClass方法
如何指定自定义ClassLoader中的parent
默认parent是appClassLoader,可以通过ClassLoader构造方法指定
存储器的层器结构
为什么要缓存行对齐
有多个CPU或者多个核,他们都有自己的高速缓存,但是高速缓存都是先从内存中的L3高速缓存中读数据,每次读一行也就是64字节。所以当多个CPU或者多个核从L3高速缓存中读了同一缓存行到他们内部的高速缓存中,当有一个CPU或核修改了缓存行中的数据,由于缓存一致性协议,会把新的数值写会到内存中,并且其他CPU或者核会把这个数据标记为失效转态,会重新从内存中读取。这样当我们想操作一个数据m的时候,就可以在这个数据m前后多创建几个对象,确保其他线程要操作数据n不在m所在的缓存行中,避免当大量修改m值得时候,其他线程需要反复去内存中重新读取这个缓存行。
如何实现缓存一致性
- 使用缓存锁(MESI): 用四种标记每个cache line的状态。有时有些无法缓存的数据或者跨越多个缓存行的数据用总线锁)
- 使用总线锁
CPU指令并写
当有多个指令进行写操作时,可以把这些指令先做完再写回内存。
当进行并写时,会把指令完成后的结果存入到一个WriteCombingBuffer,它类似于一个数组,但只有4个位置,并且它的速度比高速缓存还要快。当里面4个位置都被装满后就会写回L2。
硬件、内存级别如何实现内存屏障
sfence指令:表示执行sfence指令之前的写操作一定要在sfence指令之后的写操作之前完成。
lfence指令:同理
mfence指令
JVM级别中的规范
-
LoadLoad屏障
对于 Load1; LoadLoad; Load2这样的语句
要保证Load2读取之前,Load1已读取完毕。
-
LoadStore屏障
同理
-
StoreLoad屏障
-
StoreStore屏障
volatile实现细节
-
字节码层面
在Access flags中会标记为 volatitle
-
JVM层面
在对Volatitle内存区进行读写时,都加屏障
StoreStore 屏障
Volatitle写操作
StoreLoad 屏障
LoadLoad 屏障
Volatitle 读操作
LoadStore 屏障
-
OS和硬件层面
lock指令
Synchronized实现细节
-
字节码层面
-
如果写在方法上 Access flags 会标记这个方法为 synchronized
-
如果写在代码块上,会用两个指令实现
monitorenter moniterexit
-
-
JVM层面
会调用C/C++写的调用操作系统的同步机制
-
OS和硬件层面
X86中: lock comxchg ...
参考:
https://blog.csdn.net/21aspnet/article/details/88571740
https://blog.csdn.net/qq_26222859/article/details/52235930