网站做程序员,保洁公司用哪些网站做推广,dedecms 转 wordpress,研发项目备案在哪个网站做处理器内存模型 顺序一致性内存模型是一个理论参考模型#xff0c;JMM和处理器内存模型在设计时通常会把顺序一致性内存模型作为参照。JMM和处理器内存模型在设计时会对顺序一致性模型做一些放松#xff0c;因为如果完全按照顺序一致性模型来实现处理器和JMM#xff0c;那么… 处理器内存模型 顺序一致性内存模型是一个理论参考模型JMM和处理器内存模型在设计时通常会把顺序一致性内存模型作为参照。JMM和处理器内存模型在设计时会对顺序一致性模型做一些放松因为如果完全按照顺序一致性模型来实现处理器和JMM那么很多的处理器和编译器优化都要被禁止这对执行性能将会有很大的影响。 根据对不同类型读/写操作组合的执行顺序的放松可以把常见处理器的内存模型划分为下面几种类型 放松程序中写-读操作的顺序由此产生了total store ordering内存模型简称为TSO。在前面1的基础上继续放松程序中写-写操作的顺序由此产生了partial store order 内存模型简称为PSO。在前面1和2的基础上继续放松程序中读-写和读-读操作的顺序由此产生了relaxed memory order内存模型简称为RMO和PowerPC内存模型。 注意这里处理器对读/写操作的放松是以两个操作之间不存在数据依赖性为前提的因为处理器要遵守as-if-serial语义处理器不会对存在数据依赖性的两个内存操作做重排序。 下面的表格展示了常见处理器内存模型的细节特征 内存模型名称 对应的处理器 Store-Load 重排序 Store-Store重排序 Load-Load 和Load-Store重排序 可以更早读取到其它处理器的写 可以更早读取到当前处理器的写 TSO sparc-TSOX64 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处理器内存模型与顺序一致性内存模型之间的关系 JMM是一个语言级的内存模型处理器内存模型是硬件级的内存模型顺序一致性内存模型是一个理论参考模型。下面是语言内存模型处理器内存模型和顺序一致性内存模型的强弱对比示意图 从上图我们可以看出常见的4种处理器内存模型比常用的3中语言内存模型要弱处理器内存模型和语言内存模型都比顺序一致性内存模型要弱。同处理器内存模型一样越是追求执行性能的语言内存模型设计的会越弱。 JMM的设计 从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 BB happens- before CA happens- before C 由于A happens- before Bhappens- before的定义会要求A操作执行的结果要对B可见且A操作的执行顺序排在B操作之前。 但是从程序语义的角度来说对A和B做重排序即不会改变程序的执行结果也还能提高程序的执行性能允许这种重排序减少了对编译器和处理器优化的束缚。也就是说上面这3个happens- before关系中虽然2和3是必需要的但1是不必要的。因此JMM把happens- before要求禁止的重排序分为了下面两类 会改变程序执行结果的重排序。不会改变程序执行结果的重排序。 JMM对这两种不同性质的重排序采取了不同的策略 对于会改变程序执行结果的重排序JMM要求编译器和处理器必须禁止这种重排序。对于不会改变程序执行结果的重排序JMM对编译器和处理器不作要求JMM允许这种重排序。 下面是JMM的设计示意图 从上图可以看出两点 JMM向程序员提供的happens- before规则能满足程序员的需求。JMM的happens- before规则不但简单易懂而且也向程序员提供了足够强的内存可见性保证有些内存可见性保证其实并不一定真实存在比如上面的A happens- before B。JMM对编译器和处理器的束缚已经尽可能的少。从上面的分析我们可以看出JMM其实是在遵循一个基本原则只要不改变程序的执行结果指的是单线程程序和正确同步的多线程程序编译器和处理器怎么优化都行。比如如果编译器经过细致的分析后认定一个锁只会被单个线程访问那么这个锁可以被消除。再比如如果编译器经过细致的分析后认定一个volatile变量仅仅只会被单个线程访问那么编译器可以把这个volatile变量当作一个普通变量来对待。这些优化既不会改变程序的执行结果又能提高程序的执行效率。 JMM的内存可见性保证 Java程序的内存可见性保证按程序类型可以分为下列三类 单线程程序。单线程程序不会出现内存可见性问题。编译器runtime和处理器会共同确保单线程程序的执行结果与该程序在顺序一致性模型中的执行结果相同。正确同步的多线程程序。正确同步的多线程程序的执行将具有顺序一致性程序的执行结果与该程序在顺序一致性内存模型中的执行结果相同。这是JMM关注的重点JMM通过限制编译器和处理器的重排序来为程序员提供内存可见性保证。未同步/未正确同步的多线程程序。JMM为它们提供了最小安全性保障线程执行时读取到的值要么是之前某个线程写入的值要么是默认值0nullfalse。 下图展示了这三类程序在JMM中与在顺序一致性内存模型中的执行结果的异同 只要多线程程序是正确同步的JMM保证该程序在任意的处理器平台上的执行结果与该程序在顺序一致性内存模型中的执行结果一致。 JSR-133对旧内存模型的修补 JSR-133对JDK5之前的旧内存模型的修补主要有两个 增强volatile的内存语义。旧内存模型允许volatile变量与普通变量重排序。JSR-133严格限制volatile变量与普通变量的重排序使volatile的写-读和锁的释放-获取具有相同的内存语义。增强final的内存语义。在旧内存模型中多次读取同一个final变量的值可能会不相同。为此JSR-133为final增加了两个重排序规则。现在final具有了初始化安全性。 转载于:https://www.cnblogs.com/dengshiwei/p/4258458.html