顺序一致性内存模型 是一个理论参考模型,在设计的时候,处理器的内存模型 和编程语言的内存模型 都会以顺序一致性内存模型作为参照。 |
---|
JMM 对正确同步的多线程程序的内存一致性做了如下保证 | |
---|---|
如果程序是正确同步的,程序的执行将具有顺序一致性(Sequentially Consistent),即程序的执行结果与该程序在顺序一致性内存模型中的执行结果相同。 | 这里的同步是指广义上的同步,包括对常用同步原语(synchronized、volatile和final)的正确使用。 |
顺序一致性内存模型 |
---|
顺序一致性内存模型是一个被计算机科学家理想化了的理论参考模型 ,它为程序员提供了极强的内存可见性保证 。顺序一致性内存模型有两大特性 。 |
1)一个线程中的所有操作必须按照程序的顺序来执行。 |
2)(不管程序是否同步)所有线程都只能看到一个单一的操作执行顺序。在顺序一致性内存模型中,每个操作都必须原子执行且立刻对所有线程可见。 |
同步程序的顺序一致性效果 | |
---|---|
顺序一致性模型中,所有操作完全按程序的顺序串行执行。而在JMM中,临界区内的代码可以重排序(但JMM不允许临界区内的代码“逸出”到临界区之外,那样会破坏监视器的语义)。JMM会在退出临界区和进入临界区这两个关键时间点做一些特别处理,使得线程在这两个时间点具有与顺序一致性模型相同的内存视图。 | JMM在具体实现上的基本方针为:在不改变(正确同步的)程序执行结果的前提下,尽可能地为编译器和处理器的优化打开方便之门。 |
未同步程序的执行特性 | |
---|---|
对于未同步或未正确同步的多线程程序,JMM只提供最小安全性:线程执行时读取到的值,要么是之前某个线程写入的值 ,要么是默认值 (0,Null,False),JMM保证线程读操作读取到的值不会无中生有(Out Of Thin Air)的冒出来。 | 为了实现最小安全性,JVM在堆上分配对象时,首先会对内存空间进行清零,然后才会在上面分配对象(JVM内部会同步这两个操作)。因此,在已清零的内存空间(Pre-zeroed Memory)分配对象时,域的默认初始化已经完成了。 |
JMM不保证未同步程序的执行结果与该程序在顺序一致性模型中的执行结果一致。因为如果想要保证执行结果一致,JMM需要禁止大量的处理器和编译器的优化,这对程序的执行性能会产生很大的影响。而且未同步程序在顺序一致性模型中执行时,整体是无序的,其执行结果往往无法预知。 | 个人理解这就是所谓的 非线程安全 |
未同步程序在两个模型中的执行特性有如下几个差异 | |
---|---|
顺序一致性模型 | JMM |
顺序一致性模型保证单线程内的操作会按程序的顺序执行 | JMM不保证单线程内的操作会按程序的顺序执行。 |
顺序一致性模型保证所有线程只能看到一致的操作执行顺序, | JMM不保证所有线程能看到一致的操作执行顺序。 |
顺序一致性模型保证对所有的内存读/写操作都具有原子性。 | JMM不保证对64位的long型和double型变量的写操作具有原子性。 在JSR-133之前的旧内存模型中,一个64位long/double型变量的 读/写操作 可以被拆分为两个32位的读/写操作来执行。从JSR-133内存模型开始(即从JDK5开始),仅仅只允许把一个64位long/double型变量的写操作 拆分为两个32位的写操作来执行,任意的读操作 在JSR-133中都必须具有原子性(即任意读操作必须要在单个读事务中执行)。 |