Java内存模型如下:
线程隔离数据区:
1. 程序计数器:
用来记录每一个线程的执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等执行位置信息。
2. 虚拟机栈:
用来记录线程内的执行栈, 保存局部变量表,动态链接,方法出口等
3. 本地方法栈:
Java线程提供一个区保存跨语言的 函数入口。
线程共享区:
1. Java堆:
任何线程使用的对象(非基本数值类型)都会在Java堆中进行管理, 统一用GC回收, GC回收使用分代收集算法。不过注意Java堆分配内存有限制。
2. 方法区:
用于管理,加载类信息,常量,静态变量,即时编译器JIT编译的本地码等数据。这里的变量很少变动, 但是像不适用的一些常量,GC可能会回收。 此区为Java反射加载信息有联系。
运行时常量池: 方法区的一部分,用于存放字面量和符号引用。
3. 直接内存:
用于新加特性NIO的使用, 由于Nio复制数据,需要从线程本地方法区分配堆外内存复制到Java堆中的Buffer区, 这样会来回复制数据, 为了提高性能, 使用直接内存(物理内存),可以提高效率。
Java在多线程中的内存模型如下:
工作内存即为Java的虚拟栈,对象(主内存的备份,具体后面详述)等等。
该模型的灵感来源于CPU和内存间的操作,由于内存操作低于CPU的速度,因此存在高速缓存,该缓存内部存储部分已经操作的数据,因此存在备份,通过某一些原子操作产生一些协议来同步内存数据,从而到达加速效果。
因此,线程在操作共享数据(写时复制)的时候把主内存的数据先加载到工作内存,然后进行读写操作,相关的原子操作如下:
普通变量的读写操作如下:
可以发现,如果要达到同步效果,必须使用锁。(虚拟机的机器码优化会破坏操作顺序,也会破坏同步效果)
而加了volatile关键字后,每次操作的时候都会从主内存load, 这个关键在一些非依赖之前值的代码中可以达到同步效果。(比如:初始化开关), 而且volatile可以加入原子操作API, 达到乐观锁的效果。
观点:
1. 了解java内存模型对java开发中的一些优化很有帮助
2. 了解java多线程内存模型,可以让我们能够对其他拥有数据同步功能的理解和某些特定功能开发中提供一种参考