2018年4月1日 上午11:52
- 它是一种规范
- 他规定了虚拟机与计算机内存是如何协同工作的。它规定了一个线程如何和何时可以看到由其他线程修改过的共享变量的值。以及在必须时如何同步的访问共享变量。

- 我们需要先弄清图片里面的两个JVM 内存分配的两个概念。
- java里的的堆呢,他是一个运行时的数据区,堆是由垃圾回收来负责的。
- 堆它的优势呢,是可以动态的分配内存大小。生存期也不必事先告诉编译器,因为他是在运行时动态分配内存了,java的垃圾收集器会自动收走这些不再使用的数据。
- 但是也有缺点的,由于是要在运行时动态分配内存,因此受到存取速度相对慢一些
- 这里的栈。
- 在它的优势是存取速度比堆要快。仅次于计算机里的寄存器,栈的数据还是可以共享的。
- 但是它的缺点呢,是存在栈中的数据大小与生存期必须是确定的。缺乏一些灵活性。
- 栈主要存放一些基本类型的变量。比如我们小写的int,short,byte,float,double,char和对象句柄。
- java内存模型呢
- 要求调用栈和本地内存变量存放在线程栈(Thread Stack)上
- 对象存放在堆上。
- 我们具体说一下。一个本地变量,他也可能是指向一个对象的引用。
- 这种情况下引用这个本地变量,他是存放在这个线程栈上。
- 但是对象本身他是存放在堆上的。一个对象,他可能包含方法之类的,这方法可能包含本地变量。这里面local variable1,local variable2。
- 这些本地变量,他仍然是存放在线程栈上的,即使这些方法所属的对象存放在堆上。
- 一个对象的成员变量可能会随着这个对象自身存放在堆上。不管这个成员变量是原始类型,还是引用类型,静态成员变量跟随类的定义 一起存放在堆上。
- 存放在堆上对象可以被所持有对这个对象引用的线程访问。这边,如果我们这个Thread的存放了object的一个引用,那么它是可以访问他的。
- 当一个线程可以访问一个对象的时候呢,他也可以访问这个对象的成员变量。
- 两个线程同时调用同一个对象的同一个方法,他们将会都访问这个对象的成员变量。但是每一个线程都拥有了这个成员变量的私有拷贝。这个特别重要,就是如果两个线程里面,比如这个线程和这个线程,他们同时调用了同一个对象,这里object3,他们的同一个方法,他们都会访问这个对象的成员变量。但是呢,这两个线程他们都拥有的是这个成员变量的私有拷贝,记住了,这里是私有拷贝。

- 我们说一下他们的运作原理。
- 通常情况下,::当一个CPU需要读取主存的时候呢,它会将主存的部分数据读取到CPU缓存中。他甚至可能将缓存的部分内容读到它的内部寄存器里面。然后在寄存器中执行操作。当CPU需要将结果回起到主存的时候。他会将内部寄存器的值刷新到缓存中,然后在某个时间点就刷新回主存::

- 下来呢,我们来看一下java内存模型和硬件的内存之间的一些关联。
- 通过图呢,我们可以看出来的java内存模型与硬件内存之间存在一些差异的。硬件内存架构,它没有区分栈和堆。对于硬件而言,所有的线程,栈和堆都分布在总内存里面。有时候栈和堆可能有时候会出现在CPU缓存中和CPU内部的寄存器里面。

- 来看一下线程和主内存之间的抽象的关系
- ::线程之间的共享变量,它存储在我们的主内存里面,每个线程都有一个私有的本地内存::。
- 本地内存,他是java内存模型的一个抽象的概念,他并不是真实存在的,它涵盖了缓存,写缓存区区,寄存器以及其他的硬件和编译器的优化。
- 本地内存中他存储了该线程中已读或写, 共享变量的拷贝的一个副本。
- 比如,这里面线程如要使用主内存中的一个共享变量。他先拷贝出来这个共享变量的一个副本放在自己的本地的里面。
- 从更低的层次来说,主内存就是硬件的内存。是为了获取更好的运行速度。
- 虚拟机及硬件系统系统可能会让工作内存优先,存储于寄存器和高速缓存中。
- 那什么是的线程的工作内存。
- java内存模型中线程的工作内存,是CPU的寄存器和高速缓存的一个抽象的描述。
- 而JVM呢。静态内存存储模型就是我们JVM内存模型。它只是一种对内存的物理划分而已,他只局限在内存,而且只局限在JVM的内存。
- 现在呢,如果线程间通信。他要求必须要经过主内存。
- ::如果线程a和线程b之间要通信的话,必须要经历下面两个步骤。::
1. 第一步是线程a,要把本地的内存a中更新过的共享变量刷新到主内存里面去。 2. 线程b到主内存中去读取线程a之前已经更新过的共享变量。 - 听完这个这个可能许多人已经意识到之前演示的技术功能问题出在哪里。







- 首先java内存模型是规范。
- 它规定了一个线程如何和何时可以看到有其他线程修改过后的共享变量的值。
- 以及在必须时,如何同步的访问共享变量。
- 他要求本地变量存放在线程栈上,对象存放在堆上。
- 线程间通信必须要经过主内存。
- 同时他定义了同步的八个操作及基本规则。
- 这个呢,那我们处理并发问题提供了理论基础。后面我们对它的并发编程的一些手段都是基于java内存模型的这个规范的。