写写JMM吧,曾经我还傻傻的以为是谁把JVM写错了

我是方圆,循序渐进,按部就班

1. 什么是JMM呀?

JMM是Java Memory Mode的缩写,译成中文是Java内存模型。它定义了Java虚拟机在计算机内存中的工作方式,JMM是隶属于JVM的。
从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系,线程之间的共享变量存储于主内存中,每个线程又都有自己的工作内存。而实际上,工作内存并不存在,仅仅是一个抽象的概念,它涵盖了缓存、写缓冲区、寄存器及其他的硬件和编译器优化。

写写JMM吧,曾经我还傻傻的以为是谁把JVM写错了

2. JVM对Java内存模型的实现

  • 在JVM内部,Java内存模型把内存分成了两部分,线程栈区和堆区
    JVM中运行的每条线程都有自己的线程栈,线程栈包含了当前线程执行的方法调用相关信息,我们也把它叫做调用栈。
    写写JMM吧,曾经我还傻傻的以为是谁把JVM写错了

3. JMM带来的问题

  1. 可见性问题
    不同线程从主内存中获取值,并存储在自己的工作内存中。若对工作内存的进行修改之后,没有及时将其flush到主内存中,这就导致了不同线程*享变量值不同的问题。(可以通过加锁和关键字volatile解决)
    写写JMM吧,曾经我还傻傻的以为是谁把JVM写错了
  2. 竞争问题
    线程A和线程B共享一个对象obj。假设线程A从主存读取Obj.count变量到自己的CPU缓存,同时,线程B也读取了Obj.count变量到它的CPU缓存,并且这两个线程都对Obj.count做了加1操作。此时,Obj.count加1操作被执行了两次,不过都在不同的CPU缓存中。如果这两个加1操作是串行执行的,那么Obj.count变量便会在原始值上加2,最终主存中的Obj.count的值会是3。然而下图中两个加1操作是并行的,不管是线程A还是线程B先flush计算结果到主存,最终主存中的Obj.count只会增加1次变成2,尽管一共有两次加1操作。 (解决上面的问题我们可以使用java synchronized代码块)
    写写JMM吧,曾经我还傻傻的以为是谁把JVM写错了

参考文献

JMM和底层实现原理