注意:这是inter X86java
store fence 在sfence指令前面的写操做必须在sfence指令后边的写操做前完成c++
如图:若是没有sfence ,是不能保证操做1在操做2执行前就执行完的,有了sfence才能保证操做1和操做2的顺序面试
load fence 指令前的读操做必须在lfence指令后边的读操做执行前执行 windows
如图: 若是没有lfence 不能保证读操做1 和 读操做2 的顺序 ,有了lfence就能够保证了jvm
mix fence 是集合了sfence和lfence的全部做用于一身,mfence前边的读写操做必须在mfence后边读写操做开始以前完成布局
如图:mfence能够保证 在执行读操做2和写操做2以前 必须执行完读操做1和写操做1 this
除了fence外,还有一些原子指令 ,好比 lock xxx spa
这些原子指令是一个Full Barrier,执行时会锁住内存子系统来保证执行顺序操作系统
甚至跨多个cpucode
注意:jvm这只是jvm的规范,具体实现要看虚拟机怎么实现
保证读操做的顺序,LoadLoad前边的读操做必须在LoadLoad后边的读操做前完成
如图: LoadLoad能保证 读操做2和者读操做3执行前 必须执行完读操做0 和读操做1
对比LoadLoad 保证写操做有序
对比LoadLoad 保证读操做和写操做有序
对比 LoadLoad 保证写操做和读操做有序
这里用到jclasslib 前边文章讲过怎么安装
public class VolatileTest { int i; volatile int x; public static void main(String[] args) { } }
jclasslib 能够看出来:
i的修饰符是 0x0000[]
x的修饰符是 0x0040[volatile]
很明显,字节码层面就只是给加了volatile的属性加了一个标识
在写操做 和 读操做先后加了屏障
先后加了屏障,保证了顺序性
volatile类型变量修改以后会当即写回内存 ,也就是从工做内存写回到主内存(JMM知识)
须要使用hsdis进行反汇编,也就是把class编译成汇编指令。深刻理解Java虚拟机(第三版),448页有个例子,这里就不叙述了, 其实做为了解便可 ,底层也是经过sfence lfence mfence 或者 lock 实现的。
windows x86 是用过lock 实现的
这里须要使用hsdis ,没有太大必要去使用 ,若是有兴趣能够用一下,不是很难,之后有时间写一篇简单应用的文章。
public class TestSync { synchronized void m(){ } void n(){ synchronized (this){ } } }
一样使用jclasslib看
能够看出来 方法是用了一个标识符, 代码块使用了monitorenter monitorexit 语句
c、c++调用操做系统提供的同步机制
x86:使用的lock cmpxchg 等 指令
只是做为了解,其实工做中不多能用到,感兴趣的能够根据具体的关键字进行查询
按照字节码、jvm、操做系统硬件层面 这三个层面理解便可
最后写一个面试题你们看看能回答上来吗?
下一篇以这个题为例 写一篇文章
有问题欢迎留言,也可公众号 留言(响应快):