关于jav:话说-内存屏障有序性保证

5次阅读

共计 1572 个字符,预计需要花费 4 分钟才能阅读完成。

一、如何保障不乱序,也就是保障有序性

1、硬件内存屏障

​ 留神:这是 inter X86

1.1 sfence

​ store fence 在 sfence 指令后面的写操作必须在 sfence 指令后边的写操作前实现

如图:如果没有 sfence , 是不能保障操作 1 在操作 2 执行前就执行完的,有了 sfence 能力保障操作 1 和操作 2 的程序

1.2 lfence

load fence 指令前的读操作必须在 lfence 指令后边的读操作执行前执行

如图:如果没有 lfence 不能保障读操作 1 和 读操作 2 的程序,有了 lfence 就能够保障了

1.3 mfence

mix fence 是汇合了 sfence 和 lfence 的所有作用于一身,mfence 前边的读写操作必须在 mfence 后边读写操作开始之前实现

如图:mfence 能够保障 在执行读操作 2 和写操作 2 之前 必须执行完读操作 1 和写操作 1

1.4 其余

除了 fence 外,还有一些原子指令,比方 lock xxx

这些原子指令是一个 Full Barrier, 执行时会锁住内存子系统来保障执行程序

甚至跨多个 cpu

2.、JVM 级别标准

​ 留神:jvm 这只是 jvm 的标准,具体实现要看虚拟机怎么实现

2.1 LoadLoad 屏障

保障读操作的程序,LoadLoad 前边的读操作必须在 LoadLoad 后边的读操作前实现

如图:LoadLoad 能保障 读操作 2 和者读操作 3 执行前 必须执行完读操作 0 和读操作 1

2.2 StoreStore 屏障

比照 LoadLoad 保障写操作有序

2.3 LoadStroe 屏障

比照 LoadLoad 保障读操作和写操作有序

2.4 StoreLoad 屏障

比照 LoadLoad 保障写操作和读操作有序

3、volatile 实现细节
3.1 字节码层面

这里用到 jclasslib 前边文章讲过怎么装置

public class VolatileTest {
    int i;
    volatile int x;
    public static void main(String[] args) {}}

jclasslib 能够看进去:

i 的修饰符是 0x0000[]

x 的修饰符是 0x0040[volatile]

很显著,字节码层面就只是给加了 volatile 的属性加了一个标识

3.2 JVM 层面

在写操作 和 读操作前后加了屏障

前后加了屏障,保障了程序性

volatile 类型变量批改之后会立刻写回内存,也就是从工作内存写回到主内存(JMM 常识)

3.3 操作系统硬件层面

须要应用 hsdis 进行反汇编,也就是把 class 编译成汇编指令。深刻了解 Java 虚拟机(第三版),448 页有个例子,这里就不叙述了,其实作为理解即可,底层也是通过 sfence lfence mfence 或者 lock 实现的。

windows x86 是用过 lock 实现的

这里须要应用 hsdis,没有太大必要去应用,如果有趣味能够用一下,不是很难,当前有工夫写一篇简略利用的文章。

4、synchronize 实现细节
4.1 字节码层面
public class TestSync {synchronized  void m(){ }
    void n(){synchronized (this){}}
}

同样应用 jclasslib 看


能够看进去 办法是用了一个标识符,代码块应用了 monitorenter monitorexit 语句

4.2JVM 层面

​ c、c++ 调用操作系统提供的同步机制

4.3 操作系统硬件层面

x86: 应用的 lock cmpxchg 等 指令

只是作为理解,其实工作中很少能用到,感兴趣的能够依据具体的关键字进行查问

依照字节码、jvm、操作系统硬件层面 这三个层面了解即可

最初写一个面试题大家看看能答复上来吗?

  1. 形容一个一个对象的创立过程
  2. 对象在内存中的存储布局
  3. 对象头具体蕴含什么
  4. 对象是怎么定位的
  5. 对象怎么调配的
  6. Object o = new Object() 在内存中占用了多少字节

下一篇以这个题为例 写一篇文章

有问题欢送留言,也可公众号 留言(响应快):

正文完
 0