偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

JVM如何優(yōu)雅地分對象?揭秘HotSpot并發(fā)分配的神操作!

開發(fā) 前端
從一開始的 CAS 原子操作,到后來的 TLAB 線程劃分策略,再到按需同步、動態(tài)調(diào)優(yōu),HotSpot JVM 已經(jīng)把對象創(chuàng)建的“并發(fā)沖突”壓縮到了最低。

前言:線程一多,問題就多

那是一個平凡的工作日,我正打算下樓拿奶茶,剛要起身,就聽隔壁小王爆出一聲吼:

“我這代碼怎么突然OOM了?不是用了并發(fā)隊列嗎?”

我探過頭一看,小王的眼睛都快盯穿了堆棧日志。線程一多,對象分配就開始翻車,不是內(nèi)存亂飛,就是崩潰卡死。我們立刻意識到,幕后那個“對象分配”的黑箱得好好扒一扒了。

于是,這杯奶茶我喝得格外認(rèn)真,邊喝邊翻 JVM 的源碼,一段 HotSpot 虛擬機中處理并發(fā)對象分配的“玄機”悄然浮現(xiàn)——沒錯,我們今天要聊的主角,是 JVM 如何在高并發(fā)環(huán)境下高效且安全地分配對象內(nèi)存的秘密。

圖片圖片


對象是怎么“誕生”的?

在 Java 世界里,萬物皆對象。每當(dāng)我們執(zhí)行一句 new 操作,就相當(dāng)于按下了“制造”按鈕,JVM 背后的內(nèi)存管理機制就開始運行:

  • 首先要在堆中劃出一塊連續(xù)的內(nèi)存空間;
  • 接著對這塊空間進(jìn)行對象頭填充、字段初始化;
  • 最后把這塊“對象胚胎”交到程序手中,完成生命周期的起點。

這個過程看似簡單,但你想啊——如果上百個線程同時“點單”,這工廠還不得擠爆了?

所以,HotSpot 虛擬機到底怎么解決這個問題的呢?

謎底就是我們今天要講的兩大核心策略:

  • 同步處理:用 CAS + 失敗重試 來實現(xiàn)原子分配
  • 本地線程分配緩沖:每個線程分自己的一攤,減少鎖競爭

第一招:同步處理,CAS+失敗重試,穩(wěn)了!

在沒有 TLAB 的情況下,所有線程都要從一個“共享堆空間”里劃內(nèi)存。這個時候,“搶地盤”就成了問題。

JVM 沒有選擇加鎖,而是更優(yōu)雅地采用了 CAS(Compare-And-Swap)+ 自旋重試 的策略。

1、什么是 CAS?

CAS 是一種原子操作,允許你去比較一塊內(nèi)存的當(dāng)前值是否是你期望的,如果是就更新成新值。

比如現(xiàn)在堆的分配指針指向地址 0x1000,線程 A 想分配 100 字節(jié),它就用 CAS 嘗試把指針更新為 0x1064,如果成功,它就“占坑成功”,分配搞定。

如果失敗,說明別的線程搶先一步改了分配指針,那線程 A 就重新來一遍。

2、CAS 的優(yōu)勢:

  • 無需加鎖,性能高;
  • 是硬件級別支持的原子操作;
  • 多線程下仍然能保證數(shù)據(jù)一致性。

HotSpot 正是基于這種機制來讓對象分配“線程安全”,避免你爭我奪亂成一鍋粥。

不過,這種方式畢竟是所有線程在一個“大鍋”里搶飯吃,線程越多,CAS 失敗率就越高,效率會下降。

于是,JVM 又出了第二招。

第二招:TLAB,劃地為營,各吃各的!

還記得小時候大家搶糖吃嗎?如果所有糖果放在一個盤子里,肯定雞飛狗跳。但如果每個人發(fā)一個小袋子,就能自己慢慢吃,互不打擾。

這就是 TLAB(Thread Local Allocation Buffer)思路的靈感:

JVM 給每個線程分配一個“小堆”,線程創(chuàng)建對象時,優(yōu)先從自己的 TLAB 分配。

是不是特別熟悉?這就好比線程版的“私房錢”。

1、為什么要用 TLAB?

  • 避免線程之間的同步?jīng)_突,自己地盤自己用,爽!
  • 小對象頻繁創(chuàng)建也不會頻繁競爭鎖,極大提高性能;
  • TLAB 是在線程創(chuàng)建時初始化的,不影響其他線程的內(nèi)存分配。

當(dāng)線程使用 new 創(chuàng)建對象時,JVM 會先判斷當(dāng)前線程的 TLAB 是否還有足夠空間:

  • 有空間: 直接從 TLAB 中分配,對象創(chuàng)建快如閃電。
  • 沒空間: 就申請新的 TLAB,如果申請失敗了才回到老辦法——用 CAS 從全局堆中分配。

2、TLAB 的大小是固定的嗎?

不是。TLAB 的大小一般由 JVM 根據(jù)堆總大小、線程數(shù)、GC 頻率等動態(tài)調(diào)整,而且也可以通過參數(shù)手動干預(yù)。

比如你可以在啟動參數(shù)中控制是否啟用 TLAB:

  • -XX:+UseTLAB # 啟用(默認(rèn)開啟)
  • -XX:-UseTLAB # 禁用

還能設(shè)置分配比例等細(xì)節(jié):

  • -XX:TLABSize=512k
  • -XX:+ResizeTLAB

3、TLAB 用完了怎么辦?

TLAB 可不是無限大。一旦當(dāng)前 TLAB 用完,線程會嘗試向堆申請一個新的 TLAB。這個時候才會觸發(fā)同步機制,可能導(dǎo)致暫停、GC 或老年代分配。

所以說,TLAB 是一個優(yōu)化策略,不是銀彈。它非常適合“短平快”的對象,比如業(yè)務(wù)中頻繁構(gòu)建的臨時對象、包裝類等。

模擬生活:對象分配的快與慢

為了讓你更有畫面感,我們模擬一下現(xiàn)實場景:

有一個奶茶工廠,老板(JVM)分給每個員工(線程)一塊原料池(TLAB),大家自己打奶茶,不用排隊。只有當(dāng)原料池見底了,員工才去找倉庫經(jīng)理(堆)申請新原料(新 TLAB)。

如果這個工廠一天要出 10000 杯奶茶,光靠一個倉庫經(jīng)理肯定手忙腳亂。但每個員工有一小桶原料,效率就高了。

TLAB 就像是讓線程各自“帶著干糧上工”,分?jǐn)偭藟毫Α?/p>

深入理解:TLAB + CAS 是搭配來的

可能你注意到了一個細(xì)節(jié):哪怕使用了 TLAB,也還是會有 CAS 的影子。

那是因為創(chuàng)建新 TLAB 本身是從堆中分配空間,這個動作還是要用 CAS 保證線程安全。但因為這個過程不是每次 new 都觸發(fā),所以平均下來效率非常高。

換句話說:

  • 平時靠 TLAB,自己吃飯;
  • 用完再找 JVM,JVM 用 CAS 給你分新地盤。

這才是 HotSpot 的“并發(fā)分配兩步走”策略:分而治之 + 最小化同步。

TLAB 的開關(guān)和調(diào)優(yōu)姿勢

TLAB 并不是強制開啟的,你可以通過啟動參數(shù)控制它:

  • -XX:+UseTLAB # 啟用 TLAB(默認(rèn))
  • -XX:-UseTLAB # 禁用 TLAB
  • -XX:+PrintTLAB # 打印 TLAB 使用情況

如果你想觀察 TLAB 的命中率、利用率,可以開啟診斷命令:

  • jstat -gcutil PID 1000 5

還可以在 JFR(Java Flight Recorder)中看到 TLAB 的命中分析,精確到線程級別。

尾聲:對象分配的智慧

JVM 世界里,對象分配看似一個“小動作”,卻蘊藏了大智慧。

從一開始的 CAS 原子操作,到后來的 TLAB 線程劃分策略,再到按需同步、動態(tài)調(diào)優(yōu),HotSpot JVM 已經(jīng)把對象創(chuàng)建的“并發(fā)沖突”壓縮到了最低。

而你寫下的每一個 new,背后都經(jīng)歷了精妙的內(nèi)存布局計算、線程調(diào)度邏輯,以及無數(shù) JVM 工程師的血淚優(yōu)化。

想想看,我們是不是應(yīng)該對 JVM 稍微多一點敬意?

下次你再喝奶茶的時候,不妨想象一下那一杯“對象”,是不是正是 JVM 高效調(diào)度出來的一杯熱奶香濃呢?

責(zé)任編輯:武曉燕 來源: 軟件求生
相關(guān)推薦

2021-05-12 22:07:43

并發(fā)編排任務(wù)

2024-11-15 09:14:23

JDK4NIO函數(shù)

2023-03-26 00:43:42

JVM對象測試

2018-08-20 10:40:09

Redis位圖操作

2020-02-05 14:05:21

Java技術(shù)數(shù)組

2021-01-19 10:35:49

JVM場景函數(shù)

2021-03-24 10:20:50

Fonts前端代碼

2018-04-08 08:45:53

對象內(nèi)存策略

2022-05-24 06:07:48

JShack用戶代碼

2022-03-01 21:25:30

對象代碼Proxy

2024-11-13 16:37:00

Java線程池

2023-06-25 14:57:47

網(wǎng)絡(luò)IPv6

2021-03-28 09:17:18

JVM場景鉤子函數(shù)

2024-12-24 08:03:56

2021-01-28 14:53:19

PHP編碼開發(fā)

2024-04-24 12:34:08

Spring事務(wù)編程

2021-01-18 13:17:04

鴻蒙HarmonyOSAPP

2020-03-26 11:04:00

Linux命令光標(biāo)

2022-05-13 21:20:23

組件庫樣式選擇器

2020-07-09 10:15:55

空值Bug語言
點贊
收藏

51CTO技術(shù)棧公眾號