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

百度真題和答案解析!

開發(fā) 前端
Synchronized 作用在靜態(tài)方法是類級別的,而作用在普通方法是對象實(shí)例級別,因此作用在靜態(tài)方法時(shí),鎖范圍更大、性能也更低。

重點(diǎn)介紹一個(gè)你覺得有意義的項(xiàng)目?

回答技巧和思路:

  • 介紹的項(xiàng)目業(yè)務(wù)難度和技術(shù)難點(diǎn)要高一些,最好是微服務(wù)項(xiàng)目。
  • 簡明扼要的講清楚項(xiàng)目核心板塊的業(yè)務(wù)場景即可,切忌不要講的太細(xì)和太久,這只是面試官要考察你技術(shù)問題的一個(gè)觸手。
  • 講清楚自己在項(xiàng)目中負(fù)責(zé)的模塊。
  • 講清楚項(xiàng)目的亮點(diǎn)是啥。
  • 講清楚遇到了哪些棘手的問題?以及最終的解決方案。

synchronize鎖升級過程?

synchronized 鎖升級有兩個(gè)版本:

  • JDK 1.6 synchronized 鎖升級:無鎖 -> 偏向鎖 -> 輕量級鎖 -> 重量級鎖。
  • JDK 15 synchronized 鎖升級:無鎖 -> 輕量級鎖 -> 重量級鎖。

注意:回答的過程中,最好能講明白每種鎖的概念和特征,以及為什么 JDK 15 要廢除偏向鎖?

synchronize作用在普通方法和靜態(tài)方法上有什么區(qū)別?

synchronized 作用在靜態(tài)方法是類級別的,而作用在普通方法是對象實(shí)例級別,因此作用在靜態(tài)方法時(shí),鎖范圍更大、性能也更低。

synchronized實(shí)現(xiàn)原理?

synchronized 同步鎖是通過 JVM 內(nèi)置的 Monitor 監(jiān)視器實(shí)現(xiàn)的,而監(jiān)視器又是依賴操作系統(tǒng)的互斥鎖 Mutex 實(shí)現(xiàn)的。

例如,以下代碼中使用了 synchronized 修飾:

public class SynchronizedToMonitorExample {
    public static void main(String[] args) {
        int count = 0;
        synchronized (SynchronizedToMonitorExample.class) {
            for (int i = 0; i < 10; i++) {
                count++;
            }
        }
        System.out.println(count);
    }
}

當(dāng)我們將上述代碼編譯成字節(jié)碼之后,得到的結(jié)果是這樣的:

從上述結(jié)果我們可以看出,在 main 方法中多了一對 monitorenter 和 monitorexit 的指令,它們的含義是:

  • monitorenter:表示進(jìn)入監(jiān)視器。
  • monitorexit:表示退出監(jiān)視器。

由此可知 synchronized 是依賴 Monitor 監(jiān)視器實(shí)現(xiàn)的。

volatile作用和實(shí)現(xiàn)原理?

volatile 作用有以下兩個(gè):

  1. 保證內(nèi)存可見性;
  2. 保證有序性(禁止指令重排序)。

① 內(nèi)存可見性實(shí)現(xiàn)原理

volatile 內(nèi)存可見性主要通過 lock 前綴指令實(shí)現(xiàn)的,它會鎖定當(dāng)前內(nèi)存區(qū)域的緩存(緩存行),并且立即將當(dāng)前緩存行數(shù)據(jù)寫入主內(nèi)存(耗時(shí)非常短),回寫主內(nèi)存的時(shí)候會通過 MESI 協(xié)議使其他線程緩存了該變量的地址失效,從而導(dǎo)致其他線程需要重新去主內(nèi)存中重新讀取數(shù)據(jù)到其工作線程中。

什么 MESI 協(xié)議?

MESI 協(xié)議,全稱為 Modified, Exclusive, Shared, Invalid,是一種高速緩存一致性協(xié)議。它是為了解決多處理器(CPU)在并發(fā)環(huán)境下,多個(gè) CPU 緩存不一致問題而提出的。MESI 協(xié)議定義了高速緩存中數(shù)據(jù)的四種狀態(tài):

  • Modified(M):表示緩存行已經(jīng)被修改,但還沒有被寫回主存儲器。在這種狀態(tài)下,只有一個(gè) CPU 能獨(dú)占這個(gè)修改狀態(tài)。
  • Exclusive(E):表示緩存行與主存儲器相同,并且是主存儲器的唯一拷貝。這種狀態(tài)下,只有一個(gè) CPU 能獨(dú)占這個(gè)狀態(tài)。
  • Shared(S):表示此高速緩存行可能存儲在計(jì)算機(jī)的其他高速緩存中,并且與主存儲器匹配。在這種狀態(tài)下,各個(gè) CPU 可以并發(fā)的對這個(gè)數(shù)據(jù)進(jìn)行讀取,但都不能進(jìn)行寫操作。
  • Invalid(I):表示此緩存行無效或已過期,不能使用。

MESI 協(xié)議的主要用途是確保在多個(gè) CPU 共享內(nèi)存時(shí),各個(gè) CPU 的緩存數(shù)據(jù)能夠保持一致性。當(dāng)某個(gè) CPU 對共享數(shù)據(jù)進(jìn)行修改時(shí),它會將這個(gè)數(shù)據(jù)的狀態(tài)從 S(共享)或 E(獨(dú)占)狀態(tài)轉(zhuǎn)變?yōu)?M(修改)狀態(tài),并等待適當(dāng)?shù)臅r(shí)機(jī)將這個(gè)修改寫回主存儲器。同時(shí),它會向其他 CPU 廣播一個(gè)“無效消息”,使得其他 CPU 將自己緩存中對應(yīng)的數(shù)據(jù)狀態(tài)轉(zhuǎn)變?yōu)镮(無效)狀態(tài),從而在下次訪問這個(gè)數(shù)據(jù)時(shí)能夠從主存儲器或其他 CPU 的緩存中重新獲取正確的數(shù)據(jù)。

這種協(xié)議可以確保在多處理器環(huán)境中,各個(gè) CPU 的緩存數(shù)據(jù)能夠正確、一致地反映主存儲器中的數(shù)據(jù)狀態(tài),從而避免由于緩存不一致導(dǎo)致的數(shù)據(jù)錯(cuò)誤或程序異常。

② 有序性實(shí)現(xiàn)原理

volatile 的有序性是通過插入內(nèi)存屏障(Memory Barrier),在內(nèi)存屏障前后禁止重排序優(yōu)化,以此實(shí)現(xiàn)有序性的。

什么是內(nèi)存屏障?

內(nèi)存屏障(Memory Barrier 或 Memory Fence)是一種硬件級別的同步操作,它強(qiáng)制處理器按照特定順序執(zhí)行內(nèi)存訪問操作,確保內(nèi)存操作的順序性,阻止編譯器和 CPU 對內(nèi)存操作進(jìn)行不必要的重排序。內(nèi)存屏障可以確保跨越屏障的讀寫操作不會交叉進(jìn)行,以此維持程序的內(nèi)存一致性模型。

在 Java 內(nèi)存模型(JMM)中,volatile 關(guān)鍵字用于修飾變量時(shí),能夠保證該變量的可見性和有序性。關(guān)于有序性,volatile 通過內(nèi)存屏障的插入來實(shí)現(xiàn):

  • 寫內(nèi)存屏障(Store Barrier / Write Barrier):當(dāng)線程寫入 volatile 變量時(shí),JMM 會在寫操作前插入 StoreStore 屏障,確保在這次寫操作之前的所有普通寫操作都已完成。接著在寫操作后插入 StoreLoad 屏障,強(qiáng)制所有后來的讀寫操作都在此次寫操作完成之后執(zhí)行,這就確保了其他線程能立即看到 volatile 變量的最新值。
  • 讀內(nèi)存屏障(Load Barrier / Read Barrier):當(dāng)線程讀取 volatile 變量時(shí),JMM 會在讀操作前插入 LoadLoad 屏障,確保在此次讀操作之前的所有讀操作都已完成。而在讀操作后插入 LoadStore 屏障,防止在此次讀操作之后的寫操作被重排序到讀操作之前,這樣就確保了對 volatile 變量的讀取總是能看到之前對同一變量或其他相關(guān)變量的寫入結(jié)果。

通過這種方式,volatile 關(guān)鍵字有效地實(shí)現(xiàn)了內(nèi)存操作的順序性,從而保證了多線程環(huán)境下對 volatile 變量的操作遵循 happens-before 原則,確保了并發(fā)編程的正確性。

JVM內(nèi)存布局?

《Java虛擬機(jī)規(guī)范》中將 JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)域劃分為以下 5 部分:

  • 程序計(jì)數(shù)器(Program Counter Register):用于存儲當(dāng)前線程執(zhí)行的字節(jié)碼指令的地址,在多線程環(huán)境中,程序計(jì)數(shù)器用于實(shí)現(xiàn)線程切換,保證線程恢復(fù)執(zhí)行時(shí)能夠繼續(xù)從正確的位置執(zhí)行代碼。
  • Java 虛擬機(jī)棧(Java Virtual Machine Stacks):用于存儲方法調(diào)用和局部變量(方法內(nèi)部定義的變量),在方法調(diào)用和返回時(shí),虛擬機(jī)棧用于保存方法的調(diào)用幀,包括方法的局部變量、操作數(shù)棧、方法返回地址等。
  • 本地方法棧(Native Method Stack):與虛擬機(jī)棧類似,本地方法棧用于執(zhí)行本地(Native)方法。
  • Java 堆(Java Heap):JVM 中最大的一塊內(nèi)存區(qū)域,用于存儲對象實(shí)例。所有的對象都在堆中分配內(nèi)存。
  • 方法區(qū)(Methed Area):用于存儲類的元數(shù)據(jù)信息,包括類的結(jié)構(gòu)、字段、方法、靜態(tài)變量、常量池等。

如下圖所示:

棧和方法區(qū)會有OOM嗎?

棧和方法區(qū)都會出現(xiàn) OOM,它們的 OOM 發(fā)生場景如下:

  • 棧內(nèi)存主要用于存儲方法的棧幀,包括局部變量、操作數(shù)棧、方法返回地址等。當(dāng)一個(gè)線程請求的棧深度超過 JVM 允許的最大深度時(shí)(默認(rèn)情況下這個(gè)值是比較大的,但可以通過-Xss參數(shù)調(diào)整),會拋出 StackOverflowError 異常。此外,如果 JVM 嘗試動態(tài)擴(kuò)展??臻g大小但無法獲得足夠的內(nèi)存,也可能拋出 OutOfMemoryError 異常。不過,這種情況相對較少見,因?yàn)闂?臻g一般在啟動時(shí)就已經(jīng)固定或者有比較確定的上限。
  • 當(dāng)方法區(qū)(或元空間)中存放的類、常量、靜態(tài)變量等信息超過了 JVM 分配給它的內(nèi)存大小時(shí)(可通過 -XX:MaxMetaspaceSize 等參數(shù)進(jìn)行設(shè)置),就會拋出 OutOfMemoryError。特別是當(dāng)應(yīng)用動態(tài)加載大量的類或類加載器無法被垃圾回收時(shí),容易出現(xiàn)方法區(qū)的內(nèi)存溢出。

父線程創(chuàng)建多個(gè)子線程可能會導(dǎo)致哪塊內(nèi)存溢出?

可能會導(dǎo)致內(nèi)存溢出的區(qū)域有以下幾個(gè):

  • Java 棧內(nèi)存溢出:每個(gè)線程都有自己的棧,用于存儲方法調(diào)用時(shí)的方法信息、局部變量等數(shù)據(jù)。如果線程的棧設(shè)置過大,或者線程遞歸深度過深,可能會導(dǎo)致棧內(nèi)存溢出(StackOverflowError)。若棧大小動態(tài)擴(kuò)展受限于系統(tǒng)可用內(nèi)存,則可能拋出 OutOfMemoryError。
  • 堆內(nèi)存溢出:當(dāng)創(chuàng)建大量線程時(shí),每個(gè)線程可能會創(chuàng)建和管理多個(gè)對象,這些對象都存儲在堆中,當(dāng)對象超過 JVM 配置的最大堆內(nèi)存時(shí)(通過 -Xmx 參數(shù)設(shè)置),可能會導(dǎo)致 java.lang.OutOfMemoryError: Java heap space 錯(cuò)誤。
  • 方法區(qū)溢出: 在多線程應(yīng)用中,當(dāng)線程中的代碼涉及到動態(tài)類加載(例如使用線程上下文類加載器加載不同的類)時(shí),可能會導(dǎo)致方法區(qū)(或其替代品 Metaspace)內(nèi)存的快速增長。方法區(qū)存儲了類的元數(shù)據(jù),如果這部分內(nèi)存達(dá)到 JVM 配置的最大值(通過 -XX:MaxMetaspaceSize 設(shè)置),也會引發(fā) java.lang.OutOfMemoryError,錯(cuò)誤信息可能涉及“Metaspace”。

CMS和G1收集器的區(qū)別?

CMS 和 G1 區(qū)別主要有以下幾個(gè):

  • 目標(biāo)和定位不同:CMS 目標(biāo)和定位是最短停頓時(shí)間;G1 除了追求低停頓外,還允許用戶設(shè)定期望的最大停頓時(shí)間(Pause Time Target),更加靈活地平衡吞吐量和響應(yīng)時(shí)間,適合大規(guī)模數(shù)據(jù)的應(yīng)用。
  • 作用區(qū)域不同:CMS 是老年代垃圾回收器;G1 是全代(新生代+老年代)垃圾回收器。
  • 使用算法不同:CMS 使用的是“標(biāo)記-清除”算法,所以會產(chǎn)生內(nèi)存碎片;而 G1 使用的是“復(fù)制”算法所以不會有內(nèi)存碎片。
  • 適用場景不同:小內(nèi)存和 JDK 8 之前通常會使用 CMS 垃圾回收器;而大內(nèi)存管理和 JDK 9+ 以上環(huán)境通常會使用 G1 垃圾回收器。

說說創(chuàng)建一個(gè)對象的過程?

創(chuàng)建一個(gè)對象的過程如下:

  • 類加載檢查:當(dāng)通過 new 關(guān)鍵字創(chuàng)建一個(gè)對象時(shí),JVM 首先會檢查該對象的類是否已經(jīng)被加載并初始化了。如果尚未加載,JVM 將先進(jìn)行類的加載過程,然后調(diào)用該類的構(gòu)造器以完成初始化。
  • 分配內(nèi)存空間:類加載完成后,JVM 會在 Java 堆中為新創(chuàng)建的對象分配足夠的內(nèi)存空間。對象所需的內(nèi)存大小在類加載過程中就已經(jīng)確定。內(nèi)存的分配方式取決于 Java 堆內(nèi)存是否規(guī)整,可以選擇“指針碰撞”或“空閑列表”兩種不同的分配方式。
  • 初始化零值:內(nèi)存分配之后,JVM 會對對象的普通成員變量進(jìn)行初始化為零值,比如 int 類型初始化為 0,Integer 類型初始化為 null。這一步驟確保了對象的成員字段在不經(jīng)過顯式初始化的情況下也能被直接使用。
  • 設(shè)置對象頭:然后 JVM 需要對對象的對象頭進(jìn)行設(shè)置,這包括對象的元數(shù)據(jù)信息、GC 分代年齡、 hashCode 以及鎖標(biāo)記等。對象頭的設(shè)置對于對象的后續(xù)使用至關(guān)重要。
  • 執(zhí)行構(gòu)造方法:最后,JVM 將執(zhí)行對象的構(gòu)造方法。這一步是開發(fā)者可以控制的,可以在構(gòu)造方法中添加自定義的初始化代碼,以實(shí)現(xiàn)特定的業(yè)務(wù)邏輯。構(gòu)造方法執(zhí)行完成后,一個(gè)完全初始化且可直接使用的對象才算創(chuàng)建成功。

注意:對象創(chuàng)建過程和類加載機(jī)制(加載、驗(yàn)證、準(zhǔn)備、解析、初始化)略有不同。

責(zé)任編輯:姜華 來源: Java中文社群
相關(guān)推薦

2014-07-25 17:12:39

數(shù)據(jù)庫WOT2014MongoDB

2013-08-22 17:08:50

2018-03-09 22:56:52

PaddlePaddl

2023-05-15 18:35:47

SYN百度項(xiàng)目

2012-05-28 22:51:53

百度

2023-07-11 09:26:32

2018-09-06 18:37:45

百度云

2011-06-03 16:04:05

SEO分詞

2014-09-04 02:25:24

百度世界大會2014直達(dá)號BaiduEye

2012-10-19 09:47:30

百度云百度音樂云計(jì)算

2013-06-27 10:23:30

百度云百度開放云

2011-10-21 09:28:25

百度地圖API

2009-02-11 23:18:48

2016-03-25 11:18:23

中華網(wǎng)

2020-12-03 06:13:46

iOS

2022-03-02 11:04:45

百度業(yè)務(wù)盈利

2015-10-28 13:40:28

高仿百度糯米源碼

2011-12-08 15:31:24

百度開放平臺

2011-06-01 17:40:29

百度收錄

2011-07-11 22:16:33

百度收錄
點(diǎn)贊
收藏

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