tlab java_浅析java中的TLAB
好久,好久....沒有更博客了。這一次利用閑暇時間,來扯一下關于JVM中的TLAB。
什么是TLAB?它是干什么的?咋們先拋開這個問題,一切的開始得從new對象到指針碰撞開始講起。
new對象與指針碰撞
new對象怎么就出問題了呢?
java中我們要創建一個對象,用關鍵字new就可以了。但是,在我們日常中,有很多生命周期很短的對象。比如:
public void dome(){
User user=new user();
user.sayhi();
}
這種對象的作用域都不會逃逸出方法外,也就是說該對象的生命周期會隨著方法的調用開始而開始,方法的調用結束而結束。
假設JVM所有的對象都放在堆內存中(為什么用假設,因為JVM并不是這樣)一旦方法結束,沒有了指向該對象的引用,該對象就需要被GC回收,如果存在很多這樣的情況,對GC來說壓力山大呀。
那么什么又是指針碰撞呢?
假設JVM虛擬機上,堆內存都是規整的。堆內存被一個指針一分為二。指針的左邊都被塞滿了對象,指針的右變是未使用的區域。每一次有新的對象創建,指針就會向右移動一個對象size的距離。這就被稱為指針碰撞。
圖1.png
好,問題來了。如果我們用多線程執行剛才的dome方法,一個線程正在給A對象分配內存,指針還沒有來的及修改,同時為B對象分配內存的線程,仍引用這之前的指針指向。這樣就出現毛病了。
(要注意的是,上面兩種情況解決方案不止一個,我今天主要是講TLAB,其他方案自行查詢)
TLAB的出現
我們現在已經搞清楚,我們出現了哪些問題。我在為大家介紹一下今天的主角。
TLAB的全稱是Thread Local Allocation Buffer,即線程本地分配緩存區,這是一個線程專用的內存分配區域。
如果設置了虛擬機參數 -XX:UseTLAB,在線程初始化時,同時也會申請一塊指定大小的內存,只給當前線程使用,這樣每個線程都單獨擁有一個空間,如果需要分配內存,就在自己的空間上分配,這樣就不存在競爭的情況,可以大大提升分配效率。
TLAB空間的內存非常小,缺省情況下僅占有整個Eden空間的1%,也可以通過選項-XX:TLABWasteTargetPercent設置TLAB空間所占用Eden空間的百分比大小。
TLAB的本質其實是三個指針管理的區域:start,top 和 end,每個線程都會從Eden分配一塊空間,例如說100KB,作為自己的TLAB,其中 start 和 end 是占位用的,標識出 eden 里被這個 TLAB 所管理的區域,卡住eden里的一塊空間不讓其它線程來這里分配。
TLAB只是讓每個線程有私有的分配指針,但底下存對象的內存空間還是給所有線程訪問的,只是其它線程無法在這個區域分配而已。從這一點看,它被翻譯為 線程私有分配區 更為合理一點
當一個TLAB用滿(分配指針top撞上分配極限end了),就新申請一個TLAB,而在老TLAB里的對象還留在原地什么都不用管——它們無法感知自己是否是曾經從TLAB分配出來的,而只關心自己是在eden里分配的。
TLAB的缺點
事務總不是完美的,TLAB也又自己的缺點。因為TLAB通常很小,所以放不下大對象。
1,TLAB空間大小是固定的,但是這時候一個大對象,我TLAB剩余的空間已經容不下它了。(比如100kb的TLAB,來了個110KB的對象)
2,TLAB空間還剩一點點沒有用到,有點舍不得。(比如100kb的TLAB,裝了80KB,又來了個30KB的對象)
所以JVM開發人員做了以下處理,設置了最大浪費空間。
當剩余的空間小于最大浪費空間,那該TLAB屬于的線程在重新向Eden區申請一個TLAB空間。進行對象創建,還是空間不夠,那你這個對象太大了,去Eden區直接創建吧!
當剩余的空間大于最大浪費空間,那這個大對象請你直接去Eden區創建,我TLAB放不下沒有使用完的空間。
當然,又回造成新的病垢。
3,Eden空間夠的時候,你再次申請TLAB沒問題,我不夠了,Heap的Eden區要開始GC,
4,TLAB允許浪費空間,導致Eden區空間不連續,積少成多。以后還要人幫忙打理。
總結
以上是生活随笔為你收集整理的tlab java_浅析java中的TLAB的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: recycleviewitem 列表加载
- 下一篇: flutter天气_牛笔!自己用Flut