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

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

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() 在内存中占用了多少字节

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

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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理