最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

三道java新手入門面試題,通往自由的道路--JVM

 更新時間:2021年07月01日 09:41:56   作者:太子爺哪吒  
這篇文章主要為大家分享了最有價值的3道JVM面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對hashCode方法的設(shè)計、垃圾收集的堆和代進行剖析,感興趣的小伙伴們可以參考一下

1. 你知道JVM內(nèi)存模型嗎?

在Java的并發(fā)中采用的就是JVM內(nèi)存共享模型即JMM(Java Memory Model),它其實是是JVM規(guī)范中所定義的一種內(nèi)存模型,跟計算機的CPU緩存內(nèi)存模型類似,是基于CPU緩存內(nèi)存模型來建立的,Java內(nèi)存模型是標準化的,屏蔽掉了底層不同計算機的區(qū)別。

那我們先來講下計算機的內(nèi)存模型:

其實早期計算機中CPU和內(nèi)存的速度是差不多的,但在現(xiàn)代計算機中,CPU的指令速度遠超內(nèi)存的存取速度,由于計算機的存儲設(shè)備與處理器的運算速度有幾個數(shù)量級的差距,所以現(xiàn)代計算機系統(tǒng)都不得不加入一層讀寫速度盡可能接近處理器運算速度的高速緩存(Cache)來作為內(nèi)存與處理器之間的緩沖。

將運算需要使用到的數(shù)據(jù)復制到緩存中,讓運算能快速進行,當運算結(jié)束后再從緩存同步回內(nèi)存之中,這樣處理器就無須等待緩慢的內(nèi)存讀寫了。

基于高速緩存的存儲交互很好地解決了處理器與內(nèi)存的速度矛盾,但是也為計算機系統(tǒng)帶來更高的復雜度,因為它引入了一個新的問題:緩存一致性(CacheCoherence)。

在多處理器系統(tǒng)中,每個處理器都有自己的高速緩存,而它們又共享同一主內(nèi)存(MainMemory)。

而我們可以打開任務(wù)管理器,可以進入性能 --> CPU中可以看到L1緩存、L2緩存和L3緩存。

可以看到我們CPU跟我們計算機之間交互的高速緩存。一般的流程,就是計算機會先從硬盤從讀取數(shù)據(jù)到主內(nèi)存中,又會從主內(nèi)存讀取數(shù)據(jù)到高速緩存中,而CPU讀取的數(shù)據(jù)就是高速緩存中的數(shù)。

我們現(xiàn)在再來看看JMM:

JMM是定義了線程和主內(nèi)存之間的抽象關(guān)系:線程之間的共享變量存在主內(nèi)存(MainMemory)中,每個線程都有一個私有的本地內(nèi)存(LocalMemory)即共享變量副本,本地內(nèi)存中存儲了該線程以讀、寫共享變量的副本。本地內(nèi)存是Java內(nèi)存模型的一個抽象概念,并不真實存在。它涵蓋了緩存、寫緩沖區(qū)、寄存器等。

JMM模型圖:

我們可以發(fā)現(xiàn)在JMM模型中:

  • 所有的共享變量都存在主內(nèi)存中。
  • 每個線程都保存了一份該線程使用到的共享變量的副本。
  • 線程A是無法直接訪問到線程B的本地內(nèi)存的,只能訪問主內(nèi)存。線
  • 程對共享變量的所有操作都必須在自己的本地內(nèi)存中進行,不能直接從主內(nèi)存中讀取。
  • 并發(fā)的三要素:可見性、原子性、有序性,而JMM就主要體現(xiàn)在這三方面。

注意 :因為線程之間無法相互訪問,而一旦某個線程將共享變量進行修改,而線程B是無法發(fā)現(xiàn)到這個更新值的,所以可能會出現(xiàn)可見性問題。而這里的可見性問題就是一個線程對共享變量的修改,另一個線程能夠立刻看到,但此時無法看到更新后的內(nèi)存,因為訪問的是自己的共享變量副本。

解決方案有

  1. 加鎖,加synchronized、Lock,保存一個線程只能等另一個線程結(jié)束后才能再訪問變量。
  2. 對共享變量加上volatile關(guān)鍵字,保證了這個變量是可見的。

2. 你知道重排序是什么嗎?

重排序是指計算機在執(zhí)行程序時,為了提高性能,編譯器和處理器常常會對指令做重排。

首先我們來看看為什么指令重排序可以提高性能?

每一個指令都會包含多個步驟,每個步驟可能使用不同的硬件,而現(xiàn)代處理器會設(shè)計為一個時鐘周期完成一條執(zhí)行時間最長的指令,為什么會這樣呢?

主要原理就是可以指令1還沒有執(zhí)行完,就可以開始執(zhí)行指令2,而不用等到指令1執(zhí)行結(jié)束之后再執(zhí)行指令2,這樣就大大提高了效率。

例如:每條指令拆分為五個階段:

想這樣如果是按順序串行執(zhí)行指令,那可能相對比較慢,因為需要等待上一條指令完成后,才能等待下一步執(zhí)行:

而如果發(fā)生指令重排序呢,實際上雖然不能縮短單條指令的執(zhí)行時間,但是它變相地提高了指令的吞吐量,可以在一個時鐘周期內(nèi)同時運行五條指令的不同階段。

我們來分析下代碼的執(zhí)行情況,并思考下:

a = b + c;

d = e - f ;

按原先的思路,會先加載b和c,再進行b+c操作賦值給a,接下來就會加載e和f,最后就是進行e-f操作賦值給d。

這里有什么優(yōu)化的空間呢?我們在執(zhí)行b+c操作賦值給a時,可能需要等待b和c加載結(jié)束,才能再進行一個求和操作,所以這里可能出現(xiàn)了一個停頓等待時間,依次后面的代碼也可能會出現(xiàn)停頓等待時間,這降低了計算機的執(zhí)行效率。

為了去減少這個停頓等待時間,我們可以先加載e和f,然后再去b+c操作賦值給a,這樣做對程序(串行)是沒有影響的,但卻減少了停頓等待時間。既然b+c操作賦值給a需要停頓等待時間,那還不如去做一些有意義的事情。

總結(jié):指令重排對于提高CPU處理性能十分必要。雖然由此帶來了亂序的問題,但是這點犧牲是值得的。

重排序的類型有以下幾種:

指令重排一般分為以下三種:

  • 編譯器優(yōu)化重排

編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執(zhí)行順序。

  • 指令并行重排

現(xiàn)代處理器采用了指令級并行技術(shù)來將多條指令重疊執(zhí)行。如果不存在數(shù)據(jù)依賴性(即后一個執(zhí)行的語句無需依賴前面執(zhí)行的語句的結(jié)果),處理器可以改變語句對應(yīng)的機器指令的執(zhí)行順序。

  • 內(nèi)存系統(tǒng)重排

由于處理器使用緩存和讀寫緩存沖區(qū),這使得加載(load)和存儲(store)操作看上去可能是在亂序執(zhí)行,因為三級緩存的存在,導致內(nèi)存與緩存的數(shù)據(jù)同步存在時間差。

而在重排序中還需要一個概念的東西:as-if-serial

不管如何重排序,都必須保證代碼在單線程下的運行正確,連單線程下都無法正確,更不用討論多線程并發(fā)的情況,所以就提出了一個as-if-serial的概念。

as-if-serial語義的意思是:

  • 不管怎么重排序,程序的執(zhí)行結(jié)果不能被改變。編譯器、runtime和處理器都必須遵守as-if-serial語義。
  • 為了遵守as-if-serial語義,編譯器和處理器不會對存在數(shù)據(jù)依賴關(guān)系的操作做重排序,因為這種重排序會改變執(zhí)行結(jié)果。(強調(diào)一下,這里所說的數(shù)據(jù)依賴性僅針對單個處理器中執(zhí)行的指令序列和單個線程中執(zhí)行的操作,不同處理器之間和不同線程之間的數(shù)據(jù)依賴性不被編譯器和處理器考慮)。但是,如果操作之間不存在數(shù)據(jù)依賴關(guān)系,這些操作依然可能被編譯器和處理器重排序。

3. happens-before是什么,和as-if-serial有什么區(qū)別

happens-before的概念:

一方面,程序員需要JMM提供一個強的內(nèi)存模型來編寫代碼;另一方面,編譯器和處理器希望JMM對它們的束縛越少越好,這樣它們就可以最可能多的做優(yōu)化來提高性能,希望的是一個弱的內(nèi)存模型。

JMM考慮了這兩種需求,并且找到了平衡點,對編譯器和處理器來說,只要不改變程序的執(zhí)行結(jié)果(單線程程序和正確同步了的多線程程序),編譯器和處理器怎么優(yōu)化都行。

而對于程序員,JMM提供了happens-before規(guī)則(JSR-133規(guī)范),在JMM中,如果一個線程執(zhí)行的結(jié)果需要對另一個操作進行可見,那么這兩個操作直接必須存在happens-before關(guān)系。

JMM使用happens-before的概念來定制兩個操作之間的執(zhí)行順序。這并不意味著前一個操作必須要在后一個操作之前執(zhí)行!happens-before僅僅要求前一個操作(執(zhí)行的結(jié)果)對后一個操作可見,且前一個操作按順序排在第二個操作之前 。

happens-before關(guān)系的定義如下:

  • 如果一個操作happens-before另一個操作,那么第一個操作的執(zhí)行結(jié)果將對第二個操作可見,而且第一個操作的執(zhí)行順序排在第二個操作之前。
  • 兩個操作之間存在happens-before關(guān)系,并不意味著Java平臺的具體實現(xiàn)必須要按照happens-before關(guān)系指定的順序來執(zhí)行。如果重排序之后的執(zhí)行結(jié)果,與按happens-before關(guān)系來執(zhí)行的結(jié)果一致,那么JMM也允許這樣的重排序。
  • happens-before關(guān)系保證正確同步的多線程程序的執(zhí)行結(jié)果不被重排序改變。

在Java中,有以下天然的Happens-Before規(guī)則:

  • 程序順序規(guī)則:一個線程中的每一個操作,happens-before于該線程中的任意后續(xù)操作。
  • 監(jiān)視器鎖規(guī)則:對一個鎖的解鎖,happens-before于隨后對這個鎖的加鎖。
  • volatile變量規(guī)則:對一個volatile域的寫,happens-before于任意后續(xù)對這個volatile域的讀。
  • 傳遞性:如果A happens-before B,且B happens-before C,那么A happens-before C。
  • start規(guī)則:如果線程A執(zhí)行操作ThreadB.start()啟動線程B,那么A線程的ThreadB.start()操作happens-before于線程B中的任意操作、
  • join規(guī)則:如果線程A執(zhí)行操作ThreadB.join()并成功返回,那么線程B中的任意操作happens-before于線程A從ThreadB.join()操作成功返回。
  • 線程中斷規(guī)則:對線程interrupt()方法的調(diào)用happens-before于被中斷線程的代碼檢測到中斷事件的發(fā)生。

Happens-Before和as-if-serial的關(guān)系實質(zhì)上是一回事。

  • as-if-serial語義保證單線程內(nèi)重排序后的執(zhí)行結(jié)果和程序代碼本身應(yīng)有的結(jié)果是一致的,happens-before關(guān)系保證正確同步的多線程程序的執(zhí)行結(jié)果不被重排序改變。
  • as-if-serial語義和happens-before這么做的目的,都是為了在不改變程序執(zhí)行結(jié)果的前提下,盡可能地提高程序執(zhí)行的并行度。

總結(jié)

這篇文章就到這里了,如果這篇文章對你也有所幫助,希望您能多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Java自動生成趨勢比對數(shù)據(jù)的方法分享

    Java自動生成趨勢比對數(shù)據(jù)的方法分享

    這篇文章主要和大家分享了一種Java自動生成趨勢比對數(shù)據(jù)的方法設(shè)計及實現(xiàn),文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-04-04
  • 如何利用JAVA正則表達式輕松替換JSON中的大字段

    如何利用JAVA正則表達式輕松替換JSON中的大字段

    這篇文章主要給大家介紹了關(guān)于如何利用JAVA正則表達式輕松替換JSON中大字段的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • java 實現(xiàn)定時的方法及實例代碼

    java 實現(xiàn)定時的方法及實例代碼

    這篇文章主要介紹了java 定時任務(wù)詳細介紹及實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • java構(gòu)造器 默認構(gòu)造方法及參數(shù)化構(gòu)造方法

    java構(gòu)造器 默認構(gòu)造方法及參數(shù)化構(gòu)造方法

    構(gòu)造器也叫構(gòu)造方法、構(gòu)造函數(shù),是一種特殊類型的方法,負責類中成員變量(域)的初始化。構(gòu)造器的用處是在創(chuàng)建對象時執(zhí)行初始化,當創(chuàng)建一個對象時,系統(tǒng)會為這個對象的實例進行默認的初始化,下面文章將進入講解,需要的朋友可以參考下
    2021-10-10
  • spring-boot通過@Scheduled配置定時任務(wù)及定時任務(wù)@Scheduled注解的方法

    spring-boot通過@Scheduled配置定時任務(wù)及定時任務(wù)@Scheduled注解的方法

    這篇文章主要介紹了spring-boot通過@Scheduled配置定時任務(wù),文中還給大家介紹了springboot 定時任務(wù)@Scheduled注解的方法,需要的朋友可以參考下
    2017-11-11
  • Java分布式session存儲解決方案圖解

    Java分布式session存儲解決方案圖解

    這篇文章主要介紹了Java分布式session存儲解決方案圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • 淺談java線程join方法使用方法

    淺談java線程join方法使用方法

    這篇文章主要介紹了淺談java線程join方法使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • SpringBoot實現(xiàn)跨域的幾種常用方式總結(jié)

    SpringBoot實現(xiàn)跨域的幾種常用方式總結(jié)

    跨域是指一個域下的文檔或腳本試圖去請求另一個域下的資源,或者涉及到兩個不同域名的資源之間的交互,由于同源策略(Same Origin Policy)的限制,瀏覽器不允許跨域請求,本文小編給大家分享了SpringBoot實現(xiàn)跨域的幾種常用方式,需要的朋友可以參考下
    2023-09-09
  • maven打生產(chǎn)環(huán)境可執(zhí)行包的實現(xiàn)

    maven打生產(chǎn)環(huán)境可執(zhí)行包的實現(xiàn)

    本文主要介紹了maven打生產(chǎn)環(huán)境可執(zhí)行包的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-01-01
  • AsyncHttpClient IOExceptionFilter異常過濾器

    AsyncHttpClient IOExceptionFilter異常過濾器

    這篇文章主要為大家介紹了AsyncHttpClient IOExceptionFilter異常過濾器代碼流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12

最新評論

高安市| 昌江| 承德市| 甘洛县| 东乌珠穆沁旗| 繁峙县| 沅江市| 门头沟区| 象山县| 翼城县| 修武县| 民勤县| 营口市| 河北区| 宜宾市| 乃东县| 贵南县| 阿克苏市| 方山县| 独山县| 福鼎市| 云阳县| 陆河县| 嵊泗县| 河间市| 桓台县| 乌拉特后旗| 辉县市| 广昌县| 昭苏县| 罗甸县| 慈溪市| 木兰县| 昭通市| 延庆县| 长宁区| 沾化县| 紫阳县| 贵溪市| 泰兴市| 监利县|