顺序一致性内存模型是一个理论参考模型,JMM和处理器内存模型在设计时一般会把顺序一致性内存模型做为参照。JMM和处理器内存模型在设计时会对顺序一致性模型作一些放松,由于若是彻底按照顺序一致性模型来实现处理器和JMM,那么不少的处理器和编译器优化都要被禁止,这对执行性能将会有很大的影响。java
根据对不一样类型读/写操做组合的执行顺序的放松,能够把常见处理器的内存模型划分为下面几种类型:程序员
注意,这里处理器对读/写操做的放松,是以两个操做之间不存在数据依赖性为前提的(由于处理器要遵照as-if-serial语义,处理器不会对存在数据依赖性的两个内存操做作重排序)。编程
下面的表格展现了常见处理器内存模型的细节特征:缓存
内存模型名称安全 |
对应的处理器多线程 |
Store-Load 重排序app |
Store-Store重排序性能 |
Load-Load 和Load-Store重排序优化 |
能够更早读取到其它处理器的写spa |
能够更早读取到当前处理器的写 |
TSO |
sparc-TSO X64 |
Y |
Y |
|||
PSO |
sparc-PSO |
Y |
Y |
Y |
||
RMO |
ia64 |
Y |
Y |
Y |
Y |
|
PowerPC |
PowerPC |
Y |
Y |
Y |
Y |
Y |
在这个表格中,咱们能够看到全部处理器内存模型都容许写-读重排序,缘由在第一章以说明过:它们都使用了写缓存区,写缓存区可能致使写-读操做重排序。同时,咱们能够看到这些处理器内存模型都容许更早读到当前处理器的写,缘由一样是由于写缓存区:因为写缓存区仅对当前处理器可见,这个特性致使当前处理器能够比其余处理器先看到临时保存在本身的写缓存区中的写。
上面表格中的各类处理器内存模型,从上到下,模型由强变弱。越是追求性能的处理器,内存模型设计的会越弱。由于这些处理器但愿内存模型对它们的束缚越少越好,这样它们就能够作尽量多的优化来提升性能。
因为常见的处理器内存模型比JMM要弱,java编译器在生成字节码时,会在执行指令序列的适当位置插入内存屏障来限制处理器的重排序。同时,因为各类处理器内存模型的强弱并不相同,为了在不一样的处理器平台向程序员展现一个一致的内存模型,JMM在不一样的处理器中须要插入的内存屏障的数量和种类也不相同。下图展现了JMM在不一样处理器内存模型中须要插入的内存屏障的示意图:
如上图所示,JMM屏蔽了不一样处理器内存模型的差别,它在不一样的处理器平台之上为java程序员呈现了一个一致的内存模型。
JMM是一个语言级的内存模型,处理器内存模型是硬件级的内存模型,顺序一致性内存模型是一个理论参考模型。下面是语言内存模型,处理器内存模型和顺序一致性内存模型的强弱对比示意图:
从上图咱们能够看出:常见的4种处理器内存模型比经常使用的3中语言内存模型要弱,处理器内存模型和语言内存模型都比顺序一致性内存模型要弱。同处理器内存模型同样,越是追求执行性能的语言,内存模型设计的会越弱。
从JMM设计者的角度来讲,在设计JMM时,须要考虑两个关键因素:
因为这两个因素互相矛盾,因此JSR-133专家组在设计JMM时的核心目标就是找到一个好的平衡点:一方面要为程序员提供足够强的内存可见性保证;另外一方面,对编译器和处理器的限制要尽量的放松。下面让咱们看看JSR-133是如何实现这一目标的。
为了具体说明,请看前面提到过的计算圆面积的示例代码:
double pi = 3.14; //A double r = 1.0; //B double area = pi * r * r; //C
上面计算圆的面积的示例代码存在三个happens- before关系:
因为A happens- before B,happens- before的定义会要求:A操做执行的结果要对B可见,且A操做的执行顺序排在B操做以前。 可是从程序语义的角度来讲,对A和B作重排序即不会改变程序的执行结果,也还能提升程序的执行性能(容许这种重排序减小了对编译器和处理器优化的束缚)。也就是说,上面这3个happens- before关系中,虽然2和3是必须要的,但1是没必要要的。所以,JMM把happens- before要求禁止的重排序分为了下面两类:
JMM对这两种不一样性质的重排序,采起了不一样的策略:
下面是JMM的设计示意图:
从上图能够看出两点:
Java程序的内存可见性保证按程序类型能够分为下列三类:
下图展现了这三类程序在JMM中与在顺序一致性内存模型中的执行结果的异同:
只要多线程程序是正确同步的,JMM保证该程序在任意的处理器平台上的执行结果,与该程序在顺序一致性内存模型中的执行结果一致。
JSR-133对JDK5以前的旧内存模型的修补主要有两个:
转自:http://www.infoq.com/cn/articles/java-memory-model-7