关于Java中的内存屏障

如何打破双亲委派机制

继承ClassLoader类后重写loadClass方法

如何指定自定义ClassLoader中的parent

默认parent是appClassLoader,可以通过ClassLoader构造方法指定

存储器的层器结构

为什么要缓存行对齐

有多个CPU或者多个核,他们都有自己的高速缓存,但是高速缓存都是先从内存中的L3高速缓存中读数据,每次读一行也就是64字节。所以当多个CPU或者多个核从L3高速缓存中读了同一缓存行到他们内部的高速缓存中,当有一个CPU或核修改了缓存行中的数据,由于缓存一致性协议,会把新的数值写会到内存中,并且其他CPU或者核会把这个数据标记为失效转态,会重新从内存中读取。这样当我们想操作一个数据m的时候,就可以在这个数据m前后多创建几个对象,确保其他线程要操作数据n不在m所在的缓存行中,避免当大量修改m值得时候,其他线程需要反复去内存中重新读取这个缓存行。

如何实现缓存一致性

  1. 使用缓存锁(MESI): 用四种标记每个cache line的状态。有时有些无法缓存的数据或者跨越多个缓存行的数据用总线锁)
  2. 使用总线锁

CPU指令并写

当有多个指令进行写操作时,可以把这些指令先做完再写回内存。

当进行并写时,会把指令完成后的结果存入到一个WriteCombingBuffer,它类似于一个数组,但只有4个位置,并且它的速度比高速缓存还要快。当里面4个位置都被装满后就会写回L2。

硬件、内存级别如何实现内存屏障

sfence指令:表示执行sfence指令之前的写操作一定要在sfence指令之后的写操作之前完成。

lfence指令:同理

mfence指令

JVM级别中的规范

  1. LoadLoad屏障

    对于 Load1; LoadLoad; Load2这样的语句

    要保证Load2读取之前,Load1已读取完毕。

  2. LoadStore屏障

    同理

  3. StoreLoad屏障

  4. StoreStore屏障

volatile实现细节

  1. 字节码层面

    在Access flags中会标记为 volatitle

  2. JVM层面

    在对Volatitle内存区进行读写时,都加屏障

    StoreStore 屏障

    Volatitle写操作

    StoreLoad 屏障

    LoadLoad 屏障

    Volatitle 读操作

    LoadStore 屏障

  3. OS和硬件层面

    lock指令

Synchronized实现细节

  1. 字节码层面

    1. 如果写在方法上 Access flags 会标记这个方法为 synchronized

    2. 如果写在代码块上,会用两个指令实现

      monitorenter moniterexit

  2. JVM层面

    会调用C/C++写的调用操作系统的同步机制

  3. OS和硬件层面

    X86中: lock comxchg ...

参考:

https://blog.csdn.net/21aspnet/article/details/88571740

https://blog.csdn.net/qq_26222859/article/details/52235930

原文地址:https://www.cnblogs.com/zcr-xiaozhai/p/13817465.html