Java虚拟机 - JVM是什么?( 七 )


 
分区算法:将内存分为N块独立空间,每次只控制回收多少空间,而不是每次都针对整个空间进行回收,减少GC停顿时间 。
 
分代算法和分区算法区别:分代就是根据对象的特点进行划分,分区就是不管你是什么对象,控制每次回收多少个空间 。
 
注:GC停顿就是把在进行垃圾回收的时候,会挂起正在运行的线程,使得其不在产生新的垃圾,回收完了之后才重新运行这些线程 。
 
回收器 
注:使用参数和设置线程数这些,读者请自己去找文档 。
 
串行收集器:单线程进行垃圾回收,适用于并行能力不强的计算机(CPU),可以在新生代和老年代中使用,根据作用于不同的堆空间分为新生代串行回收器和老年代串行回收器 。
 
Serial回收器:采用复制算法,在进行垃圾回收的时候其他线程会给挂起,直到垃圾回收完成(俗称:STW,全世界停止),开启后年轻代和老年代都采用这个回收器 。
 
并行收集器:在串行的基础改为多线程并行进行垃圾回收,适用于并行能力强的计算机 。
 
ParNew回收器:适用于新生代的垃圾回收器,只是进行简单的串行多线程化,回收策略和算法和串行是一样的 。
 
ParallelGC回收器:适用于新生代,采用了复制算法的收集器,在进行垃圾回收的时候会进入STW,直到垃圾回收完成,ParallelGC是非常关注系统吞吐量 。
 
ParallelOldGC回收器:适用于老年代,ParallelGC回收器一样,但采用标记压缩算法实现
 
CMS回收器:应用于老年代的多线程回收器,采用标记清除算法,主要关注系统停顿时间,是目前主流的回收器,CMS的整个回收过程分为,初始标记、并发标记、重新标记、并发清除四个步骤,在初始标记和重新标记时会进入STW,在并发标记和并发清除的过程中是不会进入STW的,而是应用程序可以不停的工作,但CMS在回收的过程中要保证内存有足够资源,CMS回收时机是达到阈值后,触发回收,老年代默认阈值是68% 。
 
如果在CMS回收过程中,内存不足,那么则触发老年代的串行回收器,且CMS无法处理浮动垃圾(第一次告诉GC不使用,标记吧,留待第二次GC回收,第二次GC回收时告诉GC,我现在又要用了,但GC还是回收了 。)
 
注:可以通过参数设置CMS回收多少次进行碎片整理和压缩 。
 
G1回收器:采用了分区算法,独特的回收策略的多线程回收器,区分新生代和老年代依然有Eden、Sv0、Sv1区,不要求整个Eden区或新生代,老年代空间是连续的,G1的出现主要为了替代CMS,CMS采用标记清除导致出现空间碎片,对CPU资源的要求等,G1回收器是可以应用到新生代和老年代,但还是无法解决浮动垃圾等问题 。
 
JVM与多线程 
注:这里不谈论过多的多线程的内容,未来作者会单独对多线程进行撰写 。
 
JVM与多线程-图一

Java虚拟机 - JVM是什么?

文章插图
 

Java虚拟机 - JVM是什么?

文章插图
 
?
 
JVM与多线程-图二
Java虚拟机 - JVM是什么?

文章插图
 

Java虚拟机 - JVM是什么?

文章插图
 
?
 
多线程为什么需要锁?
 
在上面的时候就解释了,JVM的数据区内的方法区和堆是线程共享的,在JVM与多线程-图一说明了方法区与堆是共享的,JVM与多线程-图二则说明了线程的栈是独有的,方法是在栈中运行的,当两个线程互相抢占CPU资源,会导致执行顺序不可控,促使执行结果是不可控的 。
 
多线程锁:大体上线程并发常见的锁有,自旋锁、偏向锁、轻量锁、重量锁 。
 
自旋锁:当前线程不会进入阻塞等待锁的状态,而是会通过循环的方式尝试获取到锁 。
 
偏向锁:某个线程一直在执行某一段代码的时候,获取到锁一次,之后就默认是自动获取到锁了,是一种提高性能的方式 。
 
轻量锁:当前线程还是处于偏向锁的状态,当有别的线程在访问时则会升级为轻量锁,其他线程可以通过自旋锁进行获取 。
 
重量锁:A线程在处于轻量级锁时,B线程通过自旋的方式去尝试获取到锁,当达到自旋的阈值时还没有获取到锁,B线程则会进入阻塞状态,A线程的锁就变为重量锁 。


推荐阅读