我们继续接着上一篇的内容对JVM的运行机制进行讲解,主要是讲解运行机制的内存模型
【内存结构】
从上图中我们可以看到堆内存的划分如下:
一、刻画了Java程序运行时的堆空间,可以简述成如下2条:
1.JVM中堆空间可以分成三个大区,新生代、老年代、永久代
2.新生代可以划分为三个区,Eden区,两个幸存区
二、参数配置
1.JVM运行时堆的大小
-Xms堆的最小值
-Xmx堆空间的最大值
2.新生代堆空间大小调整
-XX:NewSize新生代的最小值
-XX:MaxNewSize新生代的最大值
-XX:NewRatio设置新生代与老年代在堆空间的大小
-XX:SurvivorRatio新生代中Eden所占区域的大小
3.永久代大小调整
-XX:MaxPermSize
4.其他
-XX:MaxTenuringThreshold,设置将新生代对象转到老年代时需要经过多少次垃圾回收,但是仍然没有被回收
在上面的配置中,老年代所占空间的大小是由-XX:SurvivorRatio这个参数进行配置的,看完了上面的JVM堆空间分配图,可能会奇怪,为啥新生代空间要划分为三个区Eden及两个Survivor区?有何用意?为什么要这么分?要理解这个问题,就得理解一下JVM的垃圾收集机制(复制算法也叫copy算法)
【内存模型】
1、每一个线程有一个工作内存和主存独立
2、工作内存存放主存中变量的值的拷贝
(1)当数据从主内存复制到工作存储时,必须出现两个动作:第一,由主内存执行的读(read)操作;第二,由工作内存执行的相应的load操作;
(2)当数据从工作内存拷贝到主内存时,也出现两个操作:第一个,由工作内存执行的存储(store)操作;第二,由主内存执行的相应的写(write)操作
(3)每一个操作都是原子的,即执行期间不会被中断
【volatile】
对于普通变量,一个线程中更新的值,不能马上反应在其他变量中,如果需要在其他线程中立即可见,需要使用 volatile 关键字
public class VolatileStopThread extends Thread{ private volatile boolean stop = false; public void stopMe(){ stop=true; } public void run(){ int i=0; while(!stop){ i++; } System.out.println("Stop thread"); } public static void main(String args[]) throws InterruptedException{ VolatileStopThread t=new VolatileStopThread(); t.start(); Thread.sleep(1000); t.stopMe(); Thread.sleep(1000); } }
没有volatile -server 运行 无法停止
volatile 不能代替锁,一般认为volatile 比锁性能好(不绝对)
选择使用volatile的条件是:语义是否满足应用
【可见性】
【有序性】
【指令重排】
【总结】
小编今天的讲解就到这里了