溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java內(nèi)存模型的規(guī)定是什么

發(fā)布時(shí)間:2021-12-29 15:47:17 來源:億速云 閱讀:102 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“Java內(nèi)存模型的規(guī)定是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

首先要明確內(nèi)存模型指什么。書中的定義是:在特定的操作協(xié)議下,對(duì)特定內(nèi)存和高速緩存進(jìn)行讀寫訪問的過程抽象。

可以知道,內(nèi)存模型就是來規(guī)定如何對(duì)內(nèi)存/緩存進(jìn)行讀寫操作的。所以Java內(nèi)存模型,就是用來定義程序?qū)ava內(nèi)存的的訪問規(guī)則。進(jìn)一步說, Java內(nèi)存模型就是定義程序中變量(靜態(tài)變量、數(shù)組對(duì)象元素等,不包括局部變量、方法參數(shù))的訪問規(guī)則。

Java內(nèi)存模型的規(guī)定:

  1. 所有變量存儲(chǔ)在主內(nèi)存中;

  2. 每個(gè)線程都有自己的工作內(nèi)存,且對(duì)變量的操作都是在工作內(nèi)存中進(jìn)行;

  3. 不同線程之間無法直接訪問彼此工作內(nèi)存中的變量,要想訪問只能通過主內(nèi)存來傳遞。

Java的線程、工作內(nèi)存、主內(nèi)存關(guān)系如下圖所示:

Java內(nèi)存模型的規(guī)定是什么
具體變量從主內(nèi)存到工作內(nèi)存,以及從工作內(nèi)存轉(zhuǎn)回主內(nèi)存的實(shí)現(xiàn)細(xì)節(jié),由下面八個(gè)原子性的操作完成:


    • lock:作用于主內(nèi)存變量,將該變量標(biāo)識(shí)為一個(gè)線程獨(dú)占的狀態(tài)

    • unlock:作用于主內(nèi)存變量,將獨(dú)占狀態(tài)釋放

    • read:作用于主內(nèi)存變量,將值拷貝到工作內(nèi)存中

    • load:作用于工作內(nèi)存中的變量,將值放到工作內(nèi)存中的變量副本中

    • use:作用于工作內(nèi)存中的變量,將值傳給執(zhí)行引擎

    • asign:作用于工作內(nèi)存中的變量,將執(zhí)行引擎中的值賦給工作內(nèi)存中的變量

    • store:作用于工作內(nèi)存中的變量,將值傳給主內(nèi)存

    • write:作用于主內(nèi)存中的變量,將工作內(nèi)存中返回的值放到主內(nèi)存變量中

同時(shí)還對(duì)上述八個(gè)操作進(jìn)行了一些細(xì)節(jié)的要求,比如read/load、store/write必須成對(duì)出現(xiàn),未執(zhí)行過lock的變量不能執(zhí)行unlock操作等。

劃重點(diǎn),此處面試常遇到的問題就是對(duì)于volatile關(guān)鍵字的解讀。

volatile關(guān)鍵字

此關(guān)鍵字修飾的變量具有兩種效果:1、保證線程間的可見性;2、阻止指令重排序

對(duì)于1的實(shí)現(xiàn),它保證load與use必須相鄰調(diào)用,即要use這個(gè)變量,必定先執(zhí)行read/load,這樣每次都能獲取到最新的變量值;它又保證asign與store必須相鄰調(diào)用,即在工作內(nèi)存中將該變量改了之后,必定會(huì)先同步到主內(nèi)存中。這樣,volatile關(guān)鍵字實(shí)現(xiàn)了可見性。至于阻止指令重排序,還是移步《深入理解Java虛擬機(jī)》一書吧,貧道水平有限,就不在這里說了。

從另一個(gè)角度來分析,Java內(nèi)存模型是圍繞著在并發(fā)過程中如何處理原子性、可見性、有序性來建立的。
原子性:八個(gè)原子性操作,以及synchronized(lock/unlock未直接開放給用戶,synchronized通過monitorenter跟monitorexit指令調(diào)用的lock/unlock操作)

  • 可見性:volatile、synchronized、final這三個(gè)關(guān)鍵字均通過不同方式實(shí)現(xiàn)了可見性

  • 有序性:volatile、synchronized  這兩個(gè)關(guān)鍵字保證有序性,同時(shí)還有先行發(fā)生(happens-before)原則來保證隱含的默認(rèn)有序性

下面說說happens-before先行發(fā)生原則,先行發(fā)生原則用通俗語言表述就是:如果操作A在操作B之前發(fā)生,那么A產(chǎn)生的影響B(tài)同樣能觀測(cè)到。那么問題來了,先行發(fā)生原則都有哪些呢?同樣有八條,如下:

  • 程序次序規(guī)則:同一個(gè)線程中按照代碼的順序依次執(zhí)行

  • 管程鎖定規(guī)則:對(duì)于同一個(gè)鎖,unlock先行發(fā)生于后面的lock,即unlock了才會(huì)lock

  • volatile變量規(guī)則:對(duì)一個(gè)volatile變量的寫操作先行發(fā)生于后面對(duì)該變量的讀操作,即寫完了才會(huì)讀

  • 線程啟動(dòng)規(guī)則:一個(gè)線程的start()方法先行發(fā)生于此線程的任何一個(gè)動(dòng)作

  • 線程終止規(guī)則:一個(gè)線程的所有動(dòng)作先行發(fā)生于該線程的終止檢測(cè)

  • 線程中斷規(guī)則:對(duì)一個(gè)線程interrupt()方法的調(diào)用先行發(fā)生于線程的中斷檢測(cè)Thread.interrpted()

  • 對(duì)象終結(jié)規(guī)則:對(duì)象的初始化完成先行發(fā)生于finalize()方法

  • 傳遞性:顧名思義,A先行發(fā)生于B,B先行發(fā)生于C,則A一定先行發(fā)生于C

“Java內(nèi)存模型的規(guī)定是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI