CMS
Concurrent Mode Failure: 當CMS收集器運行過程中年老代留給用戶程序的內(nèi)存空間不足時就會觸發(fā)這個錯誤。jvm參數(shù):-XXCMSInitiatingOccupancyFraction表示CMS啟動閥值。比如-XXCMSInitiatingOccupancyFraction=92% 表示當年老代(CMS是年老代垃圾回收算法)的內(nèi)存已經(jīng)被占用92%時則立刻開始CMS收集。
CMS特點
4個階段:
- 初始標記:很快,因為只標記GCRoot直接關聯(lián)的對象,但需要Stop The World
- 并發(fā)標記:GCRoot tracing的過程
-重新標記:修正并發(fā)標記過程中用戶程序繼續(xù)運行導致標記發(fā)生變動的那部分對象的標記記錄。需要Stop The World
-并發(fā)清除:很快
CMS有哪些缺點?
1. cpu敏感,因為CMS是跟用戶程序并行的,那么就會擠占用戶程序的計算資源,CMS的線程數(shù)=(cpu顆數(shù)+3)/4,當cpu顆數(shù)小于4時 分配給CMS的cpu資源占比就很客觀。
2. Concurrent Mode Failure問題,浮動垃圾(垃圾收集過程中又出現(xiàn)的垃圾)無法清理,可能誘發(fā)新一輪FGC
3. 標記-清除(Mark Sweep)會造成內(nèi)存碎片,為了避免內(nèi)存碎片太多導致年老代無法創(chuàng)建大對象的問題,提供了相關參數(shù)來在必要情況下進行內(nèi)存整理,這樣會消除內(nèi)存碎片但會造成停頓。
G1 收集器
特點:
1. 并發(fā)+并行:就是能夠充分利用現(xiàn)代硬件多核資源
2. 分代收集
3. 空間整合:基于標記-整理 而不是標記-清除
4. 可預測的停頓
理解GC日志
值得記住的一句話:日志中里面的參數(shù)跟使用的垃圾回收算法有關,換了算法日志就會不同。
內(nèi)存分配與回收策略
1. 對象在eden區(qū)分配,如果空間不足,觸發(fā)一次Minor GC
2. 大對象(需要大量連續(xù)內(nèi)存空間的對象,比如大數(shù)組)直接進入老年代。-XX:PretenureSizeThreshold 設置直接在老年代分配的閥值。注意:新生代(eden+survivor)采用復制算法垃圾收集
3. 長期存活的對象進入老年代
4. 動態(tài)對象年齡判斷,前三個都太死板,不夠靈活。survivor中如果相同年齡對象總和超過survivor空間的一半,那么高于或等于這個年齡的對象可以直接進入老年代。
并發(fā)編程
因為計算速度比存儲設備快的多,所以在cpu和內(nèi)存之間引入高速緩存,因為引入高速緩存所以需要解決緩存一致性問題,于是有了內(nèi)存模型:在特定的操作協(xié)議下,對特定的內(nèi)存或高速緩存進行讀寫訪問的過程抽象。
java內(nèi)存模型

8種原子操作構成主內(nèi)存和工作內(nèi)存之間的交互協(xié)議:



java內(nèi)存模型的特征
1. 原子性:read、load、assign、use、store、write都是原子的,基本數(shù)據(jù)類型的訪問和讀寫都是原子的。long和double除外。
2. 可見性:volatile,synchronized和final能夠保證可見性,即使用的時候一定是經(jīng)過主內(nèi)存同步過了。
3. 有序性
happens before
如果A先行發(fā)生于B,那么B開始執(zhí)行時一定能夠看到A的操作結果

判斷代碼是否是線程安全的,就可以用以上這些原則去逐條分析,如果滿足以上至少一條,那么就是線程安全的,否則就不是。
java線程

線程安全
CAS:樂觀鎖,但有ABA問題
synchronized 性能與ReentrantLock性能相當,后者可以綁定多個Condition