成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

靈魂拷問:Java對象的內(nèi)存分配過程是如何保證線程安全的?

開發(fā) 后端 開發(fā)工具
JVM內(nèi)存結(jié)構(gòu),是很重要的知識,相信每一個靜心準(zhǔn)備過面試的程序員都可以清楚的把堆、棧、方法區(qū)等介紹的比較清楚。

[[272058]]

 JVM內(nèi)存結(jié)構(gòu),是很重要的知識,相信每一個靜心準(zhǔn)備過面試的程序員都可以清楚的把堆、棧、方法區(qū)等介紹的比較清楚。

 

上圖,是一張在作者根據(jù)《Java虛擬機(jī)規(guī)范(Java SE 8)》中描述的JVM運(yùn)行時內(nèi)存區(qū)域結(jié)構(gòu)畫的。

很多人都知道Java對象是在堆內(nèi)存中分配空間的(JIT優(yōu)化除外),也知道內(nèi)存分配過程中是線程安全的,那么虛擬機(jī)到底是如何保證線程安全的呢?本文就來簡單介紹一下。

1.Java對象的內(nèi)存分配

我們知道,Java是一門面向?qū)ο蟮恼Z言,我們在Java中使用的對象都需要被創(chuàng)建出來,在Java中,創(chuàng)建一個對象的方法有很多種,如使用new、使用反射、使用Clone方法等,但是無論如何,對象在創(chuàng)建過程中,都需要進(jìn)行內(nèi)存分配。

拿最常見的new關(guān)鍵字舉例,當(dāng)我們使用new創(chuàng)建對象后代碼開始運(yùn)行后,虛擬機(jī)執(zhí)行到這條new指令的時候,會先檢查要new的對象對應(yīng)的類是否已被加載,如果沒有被加載則先進(jìn)行類加載。

在類加載檢查通過之后,就需要給對象進(jìn)行內(nèi)存分配了,分配的內(nèi)存主要用來存放對象的實例變量。

在進(jìn)行內(nèi)存分配時,需要根據(jù)對象中的實例變量情況等信息確定需要分配的空間大小,然后從Java堆中劃分出這樣一塊區(qū)域(假設(shè)沒有JIT優(yōu)化)。

根據(jù)JVM使用的垃圾回收器的類型,因其回收算法不同,會導(dǎo)致堆中內(nèi)存分配情況不同。如標(biāo)記-清楚算法回收后的內(nèi)存中會有大量不連續(xù)的內(nèi)存碎片,在給新的對象分配的時候,就需要通過"空閑列表"來確定一塊空閑區(qū)域。(這部分不是本文重點(diǎn),讀者可以自行學(xué)習(xí)一下。)

無論那種方式,最終都需要確定出一塊內(nèi)存區(qū)域,用于給新建對象分配內(nèi)存。我們知道,對象的內(nèi)存分配過程中,主要是對象的引用指向這個內(nèi)存區(qū)域,然后進(jìn)行初始化操作。

那么問題就來了:

在并發(fā)場景中,如何內(nèi)存分配過程的線程安全性?如果兩個線程先后把對象引用指向了同一個內(nèi)存區(qū)域,怎么辦。

2.TLAB

一般有兩種解決方案:

  • 1、對分配內(nèi)存空間的動作做同步處理,采用CAS機(jī)制,配合失敗重試的方式保證更新操作的線程安全性。
  • 2、每個線程在Java堆中預(yù)先分配一小塊內(nèi)存,然后再給對象分配內(nèi)存的時候,直接在自己這塊"私有"內(nèi)存中分配,當(dāng)這部分區(qū)域用完之后,再分配新的"私有"內(nèi)存。

方案1在每次分配時都需要進(jìn)行同步控制,這種是比較低效的。

方案2是HotSpot虛擬機(jī)中采用的,這種方案被稱之為TLAB分配,即Thread Local Allocation Buffer。這部分Buffer是從堆中劃分出來的,但是是本地線程獨(dú)享的。

這里值得注意的是,我們說TLAB時線程獨(dú)享的,但是只是在“分配”這個動作上是線程獨(dú)占的,至于在讀取、垃圾回收等動作上都是線程共享的。而且在使用上也沒有什么區(qū)別。

另外,TLAB僅作用于新生代的Eden Space,對象被創(chuàng)建的時候首先放到這個區(qū)域,但是新生代分配不了內(nèi)存的大對象會直接進(jìn)入老年代。因此在編寫Java程序時,通常多個小的對象比大的對象分配起來更加高效。

所以,雖然對象剛開始可能通過TLAB分配內(nèi)存,存放在Eden區(qū),但是還是會被垃圾回收或者被移到Survivor Space、Old Gen等。

不知道大家有沒有想過,我們使用了TLAB之后,在TLAB上給對象分配內(nèi)存時線程獨(dú)享的了,這就沒有沖突了,但是,TLAB這塊內(nèi)存自身從堆中劃分出來的過程也可能存在內(nèi)存安全問題啊。

所以,在對于TLAB的分配過程,還是需要進(jìn)行同步控制的。但是這種開銷相比于每次為單個對象劃分內(nèi)存時候?qū)M(jìn)行同步控制的要低的多。

虛擬機(jī)是否使用TLAB是可以選擇的,可以通過設(shè)置-XX:+/-UseTLAB參數(shù)來指定。

3.總結(jié)

為了保證Java對象的內(nèi)存分配的安全性,同時提升效率,每個線程在Java堆中可以預(yù)先分配一小塊內(nèi)存,這部分內(nèi)存稱之為TLAB(Thread Local Allocation Buffer),這塊內(nèi)存的分配時線程獨(dú)占的,讀取、使用、回收是線程共享的。

可以通過設(shè)置-XX:+/-UseTLAB參數(shù)來指定是否開啟TLAB分配。

【本文是51CTO專欄作者Hollis的原創(chuàng)文章,作者微信公眾號Hollis(ID:hollischuang)】

 

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2019-11-19 10:32:55

Java語言程序員

2020-06-02 07:44:04

AQS JavaNode

2024-05-20 13:13:01

線程安全Java

2020-05-29 11:48:01

安全運(yùn)維信息安全網(wǎng)絡(luò)安全

2019-08-01 10:20:10

2022-03-16 18:27:39

開發(fā)低代碼軟件開發(fā)

2015-11-16 11:22:05

Java對象內(nèi)存分配

2023-01-26 02:07:51

HashSet線程安全

2024-06-17 00:02:00

線程安全HashMapJDK 1.7

2023-03-26 00:43:42

JVM對象測試

2022-09-26 13:46:18

Java線程安全

2018-02-08 14:57:22

對象內(nèi)存分配

2021-02-23 08:58:13

Go語言變量

2019-08-12 11:14:00

JVM垃圾對象

2023-11-06 17:39:35

JavaArrayList線程

2021-07-07 12:36:10

HTTPSSSL通信

2023-10-17 00:01:34

Linux操作系統(tǒng)

2019-02-28 14:04:28

內(nèi)存固定分配存儲

2016-10-10 23:00:18

2018-04-08 08:45:53

對象內(nèi)存策略
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 国产 日韩 欧美 中文 在线播放 | 青青草综合 | 欧美精品一二三 | 一区二区免费 | 国产亚洲网站 | 久久精品国产久精国产 | 日韩 国产 在线 | 亚洲欧洲精品一区 | 国产精品亚洲成在人线 | 精品欧美一区免费观看α√ | 波多野结衣一区二区三区 | 人人九九精 | 久久久精品影院 | www.亚洲精品| 一区二区三区精品视频 | 国产美女精品视频 | 国产精品久久久久9999鸭 | 天天色av| 国产真实精品久久二三区 | www视频在线观看 | 天天拍天天插 | 一呦二呦三呦国产精品 | 国产99热在线 | 日韩区| 一区二区三区免费在线观看 | 成人av网站在线观看 | 一区二区三区四区免费视频 | 成人福利在线观看 | 欧美精品国产一区二区 | 视频一区 国产精品 | 超碰激情 | 天天拍夜夜爽 | 成人免费共享视频 | 国产成人99久久亚洲综合精品 | 蜜桃一区| 99热播放 | 久久亚洲精品国产精品紫薇 | 亚洲激情综合 | 日本在线精品视频 | 成人激情视频网 | 毛片免费观看视频 |