日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

微博二面:所有對(duì)象都一定被分配在堆中么?

來源: 責(zé)編: 時(shí)間:2023-10-27 09:14:45 260觀看
導(dǎo)讀什么是逃逸分析所謂逃逸,包括方法逃逸和線程逃逸,線程逃逸的逃逸程度高于方法逃逸(線程逃逸 > 方法逃逸):當(dāng)一個(gè)對(duì)象在方法里面被定義后,它如果被外部方法所引用(例如作為調(diào)用參數(shù)傳遞到其他方法中),這種稱為方法逃逸;可能被外

什么是逃逸分析

所謂逃逸,包括方法逃逸和線程逃逸,線程逃逸的逃逸程度高于方法逃逸(線程逃逸 > 方法逃逸):7Z328資訊網(wǎng)——每日最新資訊28at.com

當(dāng)一個(gè)對(duì)象在方法里面被定義后,它如果被外部方法所引用(例如作為調(diào)用參數(shù)傳遞到其他方法中),這種稱為方法逃逸;7Z328資訊網(wǎng)——每日最新資訊28at.com

可能被外部其他線程訪問到,譬如賦值給可以在其他線程中訪問的實(shí)例變量,這種稱為線程逃逸;7Z328資訊網(wǎng)——每日最新資訊28at.com

this 引用逃逸就是一種線程逃逸:在構(gòu)造器構(gòu)造還未徹底完成前(即實(shí)例初始化階段還未完成),將自身 this 引用向外拋出并被其他線程復(fù)制(訪問)了該引用,那么其他線程就可能會(huì)訪問到該還未被初始化的變量。7Z328資訊網(wǎng)——每日最新資訊28at.com

舉個(gè)例子:7Z328資訊網(wǎng)——每日最新資訊28at.com

public class FinalReferenceEscapeTest {     final int i;     static FinalReferenceEscapeTest obj;     public FinalReferenceEscapeTest () {          i = 1;                   // 1. 寫 final 域  obj = this;              // 2. this 引用在此 "逸出" } // 線程 A public static void writer() {   new FinalReferenceEscapeExample();  } // 線程  B public static void reader() {   if (obj != null) {      // 3    int temp = obj.i;   // 4   }  }}

假設(shè)一個(gè)線程 A 執(zhí)行 writer() 方法,另一個(gè)線程 B 執(zhí)行 reader() 方法。這里的操作 2 將自身 this 引用向外拋出,使得 FinalReferenceEscapeTest 對(duì)象還未完成構(gòu)造前就為其他線程可見。7Z328資訊網(wǎng)——每日最新資訊28at.com

有的同學(xué)可能會(huì)問,這個(gè)操作 2 不是在構(gòu)造函數(shù)的最后一步嗎,它執(zhí)行完構(gòu)造函數(shù)也執(zhí)行完了,對(duì)象不就已經(jīng)完成構(gòu)造了嗎?7Z328資訊網(wǎng)——每日最新資訊28at.com

But 這里的操作 1 和操作 2 之間可能被重排序。如下圖所示,線程 B 不能正確地讀到 i = 1,而是未初始化的 i = 0:7Z328資訊網(wǎng)——每日最新資訊28at.com

所以,我們可以得出這樣的結(jié)論:在構(gòu)造函數(shù)返回前,被構(gòu)造對(duì)象的引用不能為其他線程所見,因?yàn)榇藭r(shí)的各個(gè)字段(域)可能還沒有被初始化。7Z328資訊網(wǎng)——每日最新資訊28at.com

如果虛擬機(jī)能夠確定一個(gè)對(duì)象不會(huì)發(fā)生方法逃逸和線程逃逸,或者逃逸程度比較低(只發(fā)生方法逃逸,不發(fā)生線程逃逸),則(JIT 即時(shí)編譯器)可以為這個(gè)對(duì)象實(shí)例采取不同程度的優(yōu)化,比如鎖消除 Lock Elimination(也稱為 “同步消除 Synchronization Elimination”)、還有 棧上分配(Stack Allocations) 和 標(biāo)量替換(Scalar Replacement)等7Z328資訊網(wǎng)——每日最新資訊28at.com

棧上分配

棧上分配(Stack Allocations)是 JIT 即時(shí)編譯器的一項(xiàng)優(yōu)化技術(shù):如果確定一個(gè)對(duì)象不會(huì)逃逸出線程之外(不發(fā)生逃逸或逃逸程度較低 - 方法逃逸),那讓這個(gè)對(duì)象在棧(線程私有)上分配內(nèi)存將會(huì)是一個(gè)很不錯(cuò)的主意,對(duì)象所占用的內(nèi)存空間就可以隨棧幀出棧而銷毀。7Z328資訊網(wǎng)——每日最新資訊28at.com

在一般應(yīng)用中,完全不會(huì)逃逸的局部對(duì)象和不會(huì)逃逸出線程的對(duì)象所占的比例是很大的,如果能使用棧上分配,那大量的對(duì)象就會(huì)隨著方法的結(jié)束而自動(dòng)銷毀了,垃圾收集子系統(tǒng)的壓力將會(huì)下降很多7Z328資訊網(wǎng)——每日最新資訊28at.com

示例代碼:7Z328資訊網(wǎng)——每日最新資訊28at.com

public class StackAllocationExample {    private static final int MAX = 10000000;        public static void main(String[] args) {        long start = System.currentTimeMillis();        for (int i = 0; i < MAX; i++) {            allocateOnStack();        }        long end = System.currentTimeMillis();        System.out.println("Time taken: " + (end - start) + "ms");    }        private static void allocateOnStack() {        Point p = new Point();        p.x = 1;        p.y = 2;    }        private static class Point {        int x;        int y;    }}

在這個(gè)示例代碼中,我們定義了一個(gè)私有的靜態(tài)內(nèi)部類 Point,它包含兩個(gè) int 類型的成員變量 x 和 y。在 main 方法中,我們循環(huán)調(diào)用 allocateOnStack 方法,該方法內(nèi)部創(chuàng)建一個(gè) Point 對(duì)象并將其成員變量賦值為 1 和 2。由于 allocateOnStack 方法沒有返回 Point 對(duì)象,換言之 Point 對(duì)象是不會(huì)被暴露給其他線程的,即不會(huì)發(fā)生線程逃逸,因此編譯器可以將該對(duì)象分配在棧上而不是堆上。7Z328資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-15315-0.html微博二面:所有對(duì)象都一定被分配在堆中么?

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: DFA算法,高效實(shí)現(xiàn)敏感詞檢測(cè)與替換!

下一篇: Python字典全解析:從基礎(chǔ)到高級(jí)應(yīng)用

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 临江市| 武川县| 临洮县| 滨州市| 岳阳县| 兴宁市| 武胜县| 新巴尔虎左旗| 大埔县| 渝北区| 公主岭市| 庆安县| 凭祥市| 河源市| 木兰县| 兴化市| 封丘县| 和静县| 太白县| 吉木萨尔县| 昭觉县| 沾化县| 宣化县| 东方市| 庆阳市| 锦州市| 盐城市| 福海县| 年辖:市辖区| 那曲县| 齐河县| 凯里市| 桃园县| 上思县| 阿尔山市| 石渠县| 兴海县| 磐安县| 顺义区| 墨竹工卡县| 皮山县|