JAVA 内存模型-堆和栈:

堆栈存储结构
- 堆 存放运行时创建的对象、数组。为JVM的主内存,为所有线程共享。
- 栈 每一个jvm里的线程都拥有自己的线程栈,保存当前线程调用的方法执行的信息,引用堆区对象时 执行拷贝,在线程执行时修改拷贝对象,执行结束后再同步回堆区。一个线程只能访问自己的线程栈内的变量(从堆区拷贝的对象、方法内创建的对象、数组、以及基本数据类型)
JAVA 对象存储在堆中 、调用栈本地变量存储在线程栈中:

简单理解计算机硬件内存模型
现在的计算机通常都是多核的,最便宜的某讯云服务器都是2核的处理器。
cpu可以在某一时刻运行一个线程,多核则意味着可以支持多线程。放到Java中应用则是多线程(并发)执行。
简单的CPU硬件内存架构图

上面从上倒下存储区依次为 CPU寄存器、CPU缓存区、运行时内存主存区
主存区是共享的,而CPU部分都是封闭的
可以这样理解, Inter 9900是8核的, 则至少包含 8个CPU寄存器区块、CPU缓存区块
RAM-Main Memory 就是一根8G的内存条
此处先以单核单线程执行来理解,下面才好理解多线程的相关问题
Java运行是跑在JVM上的,JVM是在RAM上创建的。抽象的理解为JVM就是RAM主存区的一小块
CPU存储区 按读取速度依次分为 RAM-主存区(线程共享)<CPU 缓存区(线程私有)<CPU 寄存器(线程私有)
通常情况下,当一个CPU需要读取主存时,他会将主存的部分读到CPU缓存中(我理解为拷贝),也可能从缓存中读取部分内容到内存寄存器中,然后在寄存器中执行操作。当CPU需要将结果写入到主存时,他会将内部寄存器的值刷新到缓存中,然后在某个时间点将值刷新回主存区。
JVA内存模型和硬件内存架构之间的桥接

多线程
cpu包含多个核,所有的核都可并行执行线程任务,也就是支持多线程(Java并发),此时就会引发一些问题。
-
A.线程对共享变量修改的可见性
-
B.当读/写核检查共享变量时出现 race conditions(竞态条件)
共享对象的可见性
假设线程A、B线程都对count进行+1,依次开启AB线程,实际期望B线程应做 cout=2+1。但是因为B线程在读取count时,A线程并未修改后的结果写会主存取,所以B线程读取的还是count=1。

为了避免并发线程操作变量时,重新获取对状态时不能获取准确的结果。可能是存储区不同,可能是线程不同。
使用volatile 关键字修饰变量 可以保证总是从主存区读取,且如果这个变量被volatile修饰,则总是会被写入到主存区。
竞态条件(race conditions)
如果多线程操作一个资源时对访问顺序敏感,(B线程必须等A线程操作完资源后执行)就存在竞态条件,导致竞态条件发生的代码去称作临界区。
在java中 对临界区使用 同步锁 就可以避免竞态条件。如synchronized
*** END
参考:http://ifeve.com/java-memory-model-6/
网友评论