Java内存模型

66 阅读6分钟

文章目录


前言

JMM即: java内存模型
内存分配


一、指令重排

  • 指令重排对于提高CPU处理性能十分必要。虽然由此带来了乱序的问题,但是这点牺牲是值得的。
  • 指令重排可以保证串行语义一致,但是没有义务保证多线程间的语义也一致
  • 重排的具体实现方针是:在不改变(正确同步的)程序执行结果的前提下,尽量为编译期和处理器的优化打开方便之门

例如
double pi = 3.14; // A
double r = 1.0; // B
double area = pi * r * r; // C

上述操作可以描述的图形
其中 A B >> C 但是AB顺序并不会导致结果的错误,所以,AB顺序无所谓可以为如下:

可以为这样
根据happens-before的程序顺序规则,上面计算圆的面积的示例代码存在3个happensbefore关系。
1)A happens-before B。
2)B happens-before C。
3)A happens-before C。
这里的第3个happens-before关系,是根据happens-before的传递性推导出来的。

  • JMM没有保证未同步程序的执行结果与该程序在顺序一致性中执行结果一致。因为如果要保证执行结果一致,那么JMM需要禁止大量的优化,对程序的执行性能会产生很大的影响。
    • 顺序一致性模型中的每个操作必须立即对任意线程可见

二、happens-

before

1.

什么是happens-befo?

1 只要不改变程序的执行结果(单线程程序和正确同步了的多线程程序),编译器和处理器怎么优化都行。
2 如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。
3 两个操作之间存在happens-before关系,并不意味着Java平台的具体实现必须要按照happens- before关系指定的顺序来执行。如果重排序之后的执行结果,与按happens-before关系来执行的结果一致,那么JMM也允许这样的重排序。
4 如果操作A happens-before操作B,那么操作A在内存上所做的操作对操作B都是可见的,不管它们在不在一个线程。

2.

天然的happens-before关系

在Java中,有以下天然的happens-before关系:

程序顺序规则:一个线程中的每一个操作,happens-before于该线程中的任意后续操作。
监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。
start规则:如果线程A执行操作ThreadB.start()启动线程B,那么A线程的ThreadB.start()操作happens- before于线程B中的任意操作、
join规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens- before于线程A从ThreadB.join()操作成功返回。

深入理解happens-before
happens-before不是确保 线程先后顺序; 例如 A happens-before B ,确保的是 A的结果对B是可见的,无论AB是同一个线程执行,还是多个线程执行;
happens-before传送门

三、顺序一致性内存模型

顺序一致性内存模型

这个内存通过一个左右摆动的开关,可以连接到任意一个线程,同时每一个线程必须按照程序的顺序来执行内存读/写操作;

两大特点:

  • 1 一个线程中的所有操作必须按照程序的顺序来执行。
  • 2(不管程序是否同步)所有线程都只能看到一个单一的操作执行顺序。在顺序一致性内存模型中,每个操作都必须原子执行且立刻对所有线程可见。

执行效果:

  • 未同步程序在顺序一致性模型中虽然整体执行顺序是无序的,但所有线程都只能看到一个一致的整体执行顺序

这个保证是因为顺序一致性内存模型中的每个操作必须立即对任意线程可见

顺序一致性模型中,所有操作完全按程序的顺序串行执行。而在JMM中,临界区内的代码
可以重排序(但JMM不允许临界区内的代码“逸出”到临界区之外,那样会破坏监视器的语
义)。JMM会在退出临界区和进入临界区这两个关键时间点做一些特别处理,使得线程在这两
个时间点具有与顺序一致性模型相同的内存视图(具体细节后文会说明)。虽然线程A在临界
区内做了重排序,但由于监视器互斥执行的特性,这里的线程B根本无法“观察”到线程A在临
界区内的重排序。这种重排序既提高了执行效率,又没有改变程序的执行结果。

jmm模型和顺序一致性模型


总结

  1. 顺序一致性模型:
    • 保证单线程下的所有操作必须按照程序的顺序来执行,操作立即对其他线程可见;
    • 未同步的程序,执行顺序无需,单所有线程都只能看到一个一致的整体执行顺序;
  2. JMM内存模型:
    • 不保证一个线程中的代码执行顺序,为同步程序,不保证所有线程都只能看到一个一致的整体执行顺序;

    • 不保证未同步程序的执行结果与该程序在顺序一致性模型中的执行结果一致;

本文转自 jimolvxing.blog.csdn.net/article/det…,如有侵权,请联系删除。