美文网首页
程序员,请善待内存(三)--- JMM

程序员,请善待内存(三)--- JMM

作者: GableKing黑暗中漫舞 | 来源:发表于2020-03-25 00:18 被阅读0次

上集说到基于MESI缓存一致性协议的Java内存模型JMM,在MESI基础上,为了提升效率,允许指令重排序,但是引入了Java在语义方面的问题。

首先,我们写的Java源码代码生成Java虚拟机可以执行指令序列,需要经历下面几个步骤:

image

Java程序员会有疑问,我的代码会被重排序,那我要实现的逻辑和预期不一致了?

image

假如没有JMM,java程序员GG写遇到下面的情况,出现与预期不一致,100%懵逼

情况一:

数据有依赖性:(针对的是单处理单线程的数据)

  • 写后读
     a=1
     b=a
    
  • 写后写
     a=1
     a=2
    
  • 读后写
     a=b
     b=1
    

这三种操作一旦被处理器重排序,结果就会被改变


情况二:

 1 double pi = 3.14;
 2 double r = 1.0;
 3 double area = pi *r*r;

程序员的角度看,执行顺序一定是按顺序执行的,但是实际上,没有JMM的情况下,1和3有数据依赖关系,2和3有数据依赖关系,1和2的顺序因为不同处理器的重排序而执行的先后顺序不一致


JMM是java程序员使用的内存模型,在程序员的角度,内存一致性是要保证的,不需要关心不同编译器,不同处理器的重排序处理。这里,JMM需要通过内存屏障来禁止不同编译器,不同处理器的重排序行为。(遵循Snoopy协议)

什么情况下JMM会使用内存屏障呢?Store与Load操作之间,全能型屏障,而且大多数处理器都支持

JMM要为程序员们保证内存可见性。需要一套准则来保证,那就是happens-before,这个类似于JMM给程序的一种承诺。

image

那么,java程序员只要记住容易理解的happens-before原则,不去理会JMM的具体处理,放心地操控每一种硬件资源。happens-before是JMM的关键,既要程序员要求的可见性,又要减少对硬件资源的束缚。


happens before准则

happens before准则,就像我们小时候学的乘法口诀,简单好记,不用了解乘法运算具体怎么定义怎么算,掌握了它,就可以愉快的算数~

具体规则如下,敲黑板,要牢记~

. 规则一:程序的顺序性规则
一个线程中,按照程序的顺序,前面的操作happens-before后续的任何操作。

对于这一点,可能会有疑问。顺序性是指,我们可以按照顺序推演程序的执行结果,但是编译器未必一定会按照这个顺序编译,但是编译器保证结果一定==顺序推演的结果。

  1. 规则二:volatile规则

对一个volatile变量的写操作,happens-before后续对这个变量的读操作。

  1. 规则三:传递性规则

如果A happens-before B,B happens-before C,那么A happens-before C。

4.规则四:管程中的锁规则

对一个锁的解锁操作,happens-before后续对这个锁的加锁操作。这一点不难理解。

5.规则五:线程start()规则

主线程A启动线程B,线程B中可以看到主线程启动B之前的操作。也就是start() happens before 线程B中的操作。

6.规则六:线程join()规则

主线程A等待子线程B完成,当子线程B执行完毕后,主线程A可以看到线程B的所有操作。也就是说,子线程B中的任意操作,happens-before join()的返回。


嗯,JMM的核心就是几条happens-before了,是volatile,synchronized,final的内存语义基础,再上一层,是java并发的基础,其实知识就是套娃,知道它是怎么来的,是什么,解决了什么问题,缺点是什么,脉络清楚。相信有一天会质变。日拱一卒,就要这里,明天继续来分析,几个java关键字的语义,奥利给


image.png

相关文章

网友评论

      本文标题:程序员,请善待内存(三)--- JMM

      本文链接:https://www.haomeiwen.com/subject/elxzyhtx.html