国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【JUC系列-01】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理

這篇具有很好參考價(jià)值的文章主要介紹了【JUC系列-01】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

JUC系列整體欄目


內(nèi)容 鏈接地址
【一】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理 https://zhenghuisheng.blog.csdn.net/article/details/132400429
【二】深入理解CAS底層原理和基本使用 https://blog.csdn.net/zhenghuishengq/article/details/132478786
【三】熟練掌握Atomic原子系列基本使用 https://blog.csdn.net/zhenghuishengq/article/details/132543379
【四】精通Synchronized底層的實(shí)現(xiàn)原理 https://blog.csdn.net/zhenghuishengq/article/details/132740980
【五】通過(guò)源碼分析AQS和ReentrantLock的底層原理 https://blog.csdn.net/zhenghuishengq/article/details/132857564
【六】深入理解Semaphore底層原理和基本使用 https://blog.csdn.net/zhenghuishengq/article/details/132908068
【七】深入理解CountDownLatch底層原理和基本使用 https://blog.csdn.net/zhenghuishengq/article/details/133343440
【八】深入理解CyclicBarrier底層原理和基本使用 https://blog.csdn.net/zhenghuishengq/article/details/133378623

一,深入理解JMM內(nèi)存模型

1,什么是可見性

在談jmm的內(nèi)存模型之前,先了解一下并發(fā)并發(fā)編程的三大特性,分別是:可見性,原子性,有序性。可見性指的就是當(dāng)一個(gè)線程修改某個(gè)變量的值之后,其他的線程可以立馬感知到。

接下來(lái)看一個(gè)例子,看一個(gè)線程改變值之后,另一個(gè)線程能否立馬感知到這個(gè)值被改變了。

public class JmmTest {
    private boolean flag = true;
    private int count = 0;

    public void refresh() {
        flag = false;
        System.out.println(Thread.currentThread().getName() + "修改flag:"+flag);
    }

    public void load() {
        while (flag) {
            //TODO  業(yè)務(wù)邏輯
            count++;
        }
        System.out.println(Thread.currentThread().getName() + "跳出循環(huán): count=" + count);
    }

    public static void main(String[] args) throws InterruptedException {
        JmmTest test = new JmmTest();

        // 線程threadA模擬數(shù)據(jù)加載場(chǎng)景
        Thread threadA = new Thread(() -> test.load(), "threadA");
        threadA.start();

        // 讓threadA執(zhí)行一會(huì)兒
        Thread.sleep(1000);
        // 線程threadB通過(guò)flag控制threadA的執(zhí)行時(shí)間
        Thread threadB = new Thread(() -> test.refresh(), "threadB");
        threadB.start();
    }
}

可以發(fā)現(xiàn)以上操作,線程A先加載這個(gè)flag值,由于是true,因此一直處于while循環(huán)中空轉(zhuǎn),但是線程B隨后修改了這個(gè)值,但是可以發(fā)現(xiàn)線程A是還在這個(gè)while循環(huán)中的,并沒(méi)有跳出循環(huán),其結(jié)果值如下:

threadB修改flag:false

也就是說(shuō),在一個(gè)正常的多線程之間的通信,是不能夠直接的進(jìn)行通信的,因此這就需要了解JMM的底層原理了

2,什么是JMM

Java Memory Model ,就是JMM的全稱,意思是java內(nèi)存模型。主要用于規(guī)范java虛擬機(jī)和計(jì)算機(jī)內(nèi)存時(shí)如何協(xié)調(diào)工作的,規(guī)定了當(dāng)一個(gè)線程改變某個(gè)共享變量值后,其他線程需要如何查看以及合適可以查看這個(gè)被改變的共享數(shù)據(jù)。

jmm的內(nèi)存模型如下,java采用的是共享變量的模型方式,在創(chuàng)建一個(gè)共享變量之后,這些共享變量時(shí)存儲(chǔ)在主內(nèi)存中的,所有線程都能訪問(wèn),但是每個(gè)線程需要操作這個(gè)變量時(shí),需要先將這個(gè)值加載到每個(gè)線程的工作內(nèi)存中,即每個(gè)線程都有對(duì)應(yīng)棧幀,將這個(gè)值加入到局部變量表即可,就成為了共享變量的一個(gè)副本,隨后線程A才能去修改這個(gè)值

【JUC系列-01】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理,JUC系列,java,JUC,內(nèi)存屏障,JMM,volatile,LoadStore,并發(fā)編程

而由于主內(nèi)存中的變量都是共享變量,因此為了解決并發(fā)問(wèn)題,在JMM內(nèi)部又引入了八大原子操作

1,lock:作用于主內(nèi)存的變量,把一個(gè)變量標(biāo)記為一條線程獨(dú)占狀態(tài)
2,unlock:把一個(gè)處于鎖定狀態(tài)的變量釋放出來(lái),釋放后的變量才可以被其他線程鎖定
3,read(讀取):作用于主內(nèi)存中,需要先對(duì)變量進(jìn)行副本的拷貝,然后將變量值傳輸?shù)焦ぷ鲀?nèi)存中
4,load(載入):在工作內(nèi)存中,需要對(duì)傳輸過(guò)來(lái)的副本變量進(jìn)行一個(gè)獲取,并且存入到工作內(nèi)存中
5,use(使用): 需要將獲取的變量傳給執(zhí)行引擎
6,assign(賦值):執(zhí)行引擎會(huì)將這個(gè)收到的變量賦值給工作內(nèi)存的變量
7,store(存儲(chǔ)):修改這個(gè)傳過(guò)來(lái)的副本之后,會(huì)將修改的值存儲(chǔ)并送到主內(nèi)存中
8,write(寫入):會(huì)將這個(gè)存儲(chǔ)的變量寫回到主內(nèi)存中,即修改主內(nèi)存的值

如當(dāng)一個(gè)線程去修改主內(nèi)存中的共享變量的方式如下,比如說(shuō)內(nèi)存中的 x = 5 進(jìn)行 +1 的操作如下圖所示,首先線程A會(huì)read讀取主內(nèi)存中的x = 5的值,隨后將讀取到的值load載入到線程A的本地內(nèi)存中,一般棧幀中存放變量的都是這個(gè)局部變量表,隨后會(huì)通過(guò)use的指令使用這個(gè)變量,將這個(gè)值加入到cpu中,結(jié)果cpu內(nèi)部的運(yùn)算之后,此時(shí) x = 6,會(huì)通過(guò)assign方式將這個(gè)結(jié)果值從cpu返回到本地內(nèi)存中,隨后將這個(gè)值返回到主內(nèi)存中,并通過(guò)store的方式將這個(gè)值存儲(chǔ),最后將被修改的變量寫回到主內(nèi)存中。

【JUC系列-01】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理,JUC系列,java,JUC,內(nèi)存屏障,JMM,volatile,LoadStore,并發(fā)編程

同時(shí)在使用這八種原子操作時(shí),需要滿足以下的規(guī)則

  • 如果要把一個(gè)變量從主內(nèi)存中復(fù)制到工作內(nèi)存,就需要按順尋地執(zhí)行read和load操作, 如果把變量從工作內(nèi)存中同步回主內(nèi)存中,就要按順序地執(zhí)行store和write操作。但Java內(nèi)存模型只要求上述操作必須按順序執(zhí)行,而沒(méi)有保證必須是連續(xù)執(zhí)行。
  • 不允許read和load、store和write操作之一單獨(dú)出現(xiàn)
  • 不允許一個(gè)線程丟棄它的最近assign的操作,即變量在工作內(nèi)存中改變了之后必須同步到主內(nèi)存中。
  • 不允許一個(gè)線程無(wú)原因地(沒(méi)有發(fā)生過(guò)任何assign操作)把數(shù)據(jù)從工作內(nèi)存同步回主內(nèi)存中。
  • 一個(gè)新的變量只能在主內(nèi)存中誕生,不允許在工作內(nèi)存中直接使用一個(gè)未被初始化(load或assign)的變量。即就是對(duì)一個(gè)變量實(shí)施use和store操作之前,必須先執(zhí)行過(guò)了assign和load操作。
  • 一個(gè)變量在同一時(shí)刻只允許一條線程對(duì)其進(jìn)行l(wèi)ock操作,但lock操作可以被同一條線程重復(fù)執(zhí)行多次,多次執(zhí)行l(wèi)ock后,只有執(zhí)行相同次數(shù)的unlock操作,變量才會(huì)被解鎖。lock和unlock必須成對(duì)出現(xiàn)
  • 如果對(duì)一個(gè)變量執(zhí)行l(wèi)ock操作,將會(huì)清空工作內(nèi)存中此變量的值,在執(zhí)行引擎使用這個(gè)變量前需要重新執(zhí)行l(wèi)oad或assign操作初始化變量的值
  • 如果一個(gè)變量事先沒(méi)有被lock操作鎖定,則不允許對(duì)它執(zhí)行unlock操作;也不允許去unlock一個(gè)被其他線程鎖定的變量。
  • 對(duì)一個(gè)變量執(zhí)行unlock操作之前,必須先把此變量同步到主內(nèi)存中(執(zhí)行store和write操作)。

3,引入volatile

在了解完這個(gè)jmm內(nèi)存模型之后,知道java線程之間是如何進(jìn)行線程通信的,再回到這個(gè) JmmTest 方法中,現(xiàn)在可以大膽的猜測(cè)一下,是不是因?yàn)榫€程B修改完值后,沒(méi)有人去通知線程A?所以才導(dǎo)致值沒(méi)有發(fā)生變化

因此接下來(lái)繼續(xù)驗(yàn)證,就是直接在這個(gè)flag變量前面增加一個(gè)關(guān)鍵字 volatile

private volatile boolean flag = true;

其結(jié)果如下,可以得出結(jié)論,線程A跳出了循環(huán),就是意味著線程A接收到了這個(gè)最新的值

threadB修改flag:false
threadA跳出循環(huán): count=399766740

因此查閱了一些資料,以及看了一下hotspot里面關(guān)于這個(gè)volatile關(guān)鍵字的源碼,可以發(fā)現(xiàn)這個(gè)關(guān)鍵字是通過(guò)一個(gè)JVM的內(nèi)存屏障來(lái)實(shí)現(xiàn)的。

storeload();  //jvm內(nèi)存屏障,在匯編指令中,對(duì)應(yīng)著lock關(guān)鍵字

內(nèi)存屏障可以禁止該指令與前面和后面的讀寫指令重排序,并且可以使其他線程中的本地內(nèi)存中的該值直接失效,這樣其他內(nèi)存就需要去主內(nèi)存中獲取改值,就能拿到最新的值了。因此volatile是通過(guò)內(nèi)存屏障的方式來(lái)實(shí)現(xiàn)數(shù)據(jù)的可見性和有序性的。

除了這個(gè)volatile關(guān)鍵字之外,另外像synchronized,lock等這些鎖底層都是采用了這個(gè)內(nèi)存屏障來(lái)實(shí)現(xiàn),因此這些重量級(jí)鎖肯定也是可以保證可見性和有序性的,同時(shí)由于是重量級(jí)操作,除了這兩種之外,他們同時(shí)還能保證原子性。

除了內(nèi)存屏障可以保證可見性之外,關(guān)鍵字final也是可以保證可見性的??偠灾鼙WC可見性的方式只有兩種:一種是內(nèi)存屏障,一種是上下文切換

4,cpu緩存架構(gòu)

在cpu中,主要由寄存器,程序計(jì)數(shù)器,高速緩存,邏輯運(yùn)算單元組成,高速緩存又分了三級(jí)緩存,分別是一級(jí)緩存、二級(jí)緩存和三級(jí)緩存,一級(jí)緩存中又分為兩部分,一個(gè)用于存儲(chǔ)指令,一個(gè)用于存儲(chǔ)數(shù)據(jù)。在inter處理器中,一個(gè)cpu又分為兩個(gè)處理器,因此會(huì)存在兩個(gè)cpu共享一個(gè)三級(jí)緩存的情況。

【JUC系列-01】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理,JUC系列,java,JUC,內(nèi)存屏障,JMM,volatile,LoadStore,并發(fā)編程

使用高速緩存主要是減少等待內(nèi)存的時(shí)間,提升CPU的計(jì)算能力

接下來(lái)根據(jù)這個(gè)緩存架構(gòu)再舉一個(gè)例子,現(xiàn)在有兩個(gè)線程,分別是線程thread1和線程thread2,假設(shè)主內(nèi)存中有一個(gè)值x=100,接下來(lái)兩個(gè)線程同時(shí)去讀這個(gè)100,線程1加對(duì)這個(gè)值加10,線程2對(duì)這個(gè)值加20,那么根據(jù)JMM的八大原子操作,此時(shí)線程1的CPU的值為110,線程2的CPU的值為120,最終會(huì)將這個(gè)值寫回主內(nèi)存中。

那么此時(shí)主內(nèi)存就會(huì)出現(xiàn)兩種情況,如果線程1先寫回,線程2后寫回,那么線程2會(huì)將線程1寫回的值覆蓋掉,此時(shí);如果線程2先寫回,線程后寫回,那么線程會(huì)將線程2寫回的值給覆蓋掉,這就是經(jīng)典的線程不安全問(wèn)題

【JUC系列-01】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理,JUC系列,java,JUC,內(nèi)存屏障,JMM,volatile,LoadStore,并發(fā)編程

造成這種原因的主要問(wèn)題,是因?yàn)榫彺娌灰恢碌膯?wèn)題。 即線程1的高速緩存的值和線程2的高速緩存的值不一致所導(dǎo)致的,因此為了解決這種緩存一致性的問(wèn)題,主要有兩種解決方式:嗅探機(jī)制、基于目錄的機(jī)制

5,嗅探機(jī)制

再了解完這個(gè)導(dǎo)致數(shù)據(jù)不安全的原因是由于緩存不一致的問(wèn)題,因此為了解決這個(gè)硬件層面的緩存一致性,最流行的還是使用這種嗅探機(jī)制。

其工作原理如下:就是說(shuō)如果存在多個(gè)緩存被共享的時(shí)候,如果有處理器修改了共享變量的值,那么必須傳播到其他所有具有該變量的副本中,通過(guò)這種傳播機(jī)制來(lái)防止系統(tǒng)違反緩存的一致性。就是說(shuō),數(shù)據(jù)的變更通知是通過(guò)總線來(lái)完成的。當(dāng)其他緩存接收到這個(gè)通知信息之后,可以選擇重新的在主內(nèi)存中刷新數(shù)據(jù),也可以直接讓當(dāng)前緩存中的值直接失效,具體是哪種做法,還得取決于使用哪種緩存一致性協(xié)議。

寫失效:就是某個(gè)處理器將值改完之后,直接通知其他處理器,讓其他處理器的緩存值失效

寫更新:就是處理器將值修改完之后,在通知其他處理器的時(shí)候,直接將值攜帶上,讓其他的處理器緩存值更新

總線的帶寬是有效的,因此寫失效的使用范圍是最廣的。MSI、MESI、MOSI、MOESI等是最常見的緩存一致性協(xié)議

6,解決緩存一致性的MESI

為了解決緩存一致性,使用最多的方式是這種MESI的方式,總共有四種狀態(tài),分別是

  • M:modify,修改狀態(tài)
  • E:Exclusive,獨(dú)占狀態(tài)
  • S:Share,共享狀態(tài)
  • I:Invalid,失效狀態(tài)

【JUC系列-01】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理,JUC系列,java,JUC,內(nèi)存屏障,JMM,volatile,LoadStore,并發(fā)編程

當(dāng)工作內(nèi)存將主內(nèi)存的值加載到高速緩存之后,假設(shè)此時(shí)只有當(dāng)前線程thread1加載了X=5,那么此時(shí)X是一個(gè)Exclusive獨(dú)占狀態(tài),如果此時(shí)線程thread2也加載了這個(gè)值,那么此時(shí)該值則會(huì)從一個(gè)獨(dú)占狀態(tài)變成一個(gè)Share共享狀態(tài),如果此時(shí)線程thread1要修改這個(gè)值,那么在修改這個(gè)值后,X就會(huì)從一個(gè)共享狀態(tài)變?yōu)橐粋€(gè)Modify修改狀態(tài),并且在回顯的時(shí)候被總線窺探到,總線就會(huì)發(fā)起請(qǐng)求告訴其他的線程這個(gè)被修改的值,讓其他的線程緩存里面的改值直接失效Invalid,那么其他線程就可以去獲取最新的值。

但是該協(xié)議并不是會(huì)直接生效,而是需要在特定的時(shí)候生效,就是需要一個(gè)lock前綴指令才可以滿足該協(xié)議,如一些常見的volatile,synchronized,lock等關(guān)鍵字。這樣才能解決這種緩存一致性的問(wèn)題。但是volatile并不能保證原子性。

并且在某個(gè)線程更新了某個(gè)值之后,刷新主內(nèi)存的線程會(huì)立即執(zhí)行,這樣才能讓其他已經(jīng)處于失效的線程立馬的回到主內(nèi)存中去更新改值,從而線程在獲取值時(shí)減少數(shù)據(jù)的臟讀問(wèn)題以及長(zhǎng)時(shí)間等待的問(wèn)題。 通過(guò)緩存一致性,來(lái)保證在多線程的情況下實(shí)現(xiàn)共享變量的可見性

除了緩存一致性協(xié)議之外,還有總線一致性協(xié)議,由于總線一致性的性能問(wèn)題,緩存一致性協(xié)議才得以出現(xiàn)。

7,JMM內(nèi)存可見性的保證

在單線程中:由于需要保證 else-if-serial 規(guī)范,即不管如何進(jìn)行指令重排,都必須要保證最終結(jié)果的一致性,因此,單線程不存在內(nèi)存可見性的問(wèn)題,不管是編譯器還是及時(shí)處理器等,都必須保證和原始順序所執(zhí)行的結(jié)果值相同

在正確同步的多線程中:如在加鎖的情況下,JMM在內(nèi)部會(huì)禁止指令重排的操作,并且在底層會(huì)通過(guò)內(nèi)存屏障的操作來(lái)操作底層硬件,從而實(shí)現(xiàn)可見性和有序性的操作。

未同步的多線程:JMM不能保證未同步的執(zhí)行結(jié)果與順序一致性的結(jié)果一致。由于在JVM中,存在一些JIT即時(shí)編譯器以及解釋器的一些優(yōu)化等,因此就會(huì)出現(xiàn)指令重排的情況。

x = 10;						y = 100;													
y = 100;          ====>		x = 10;
z = x + 10;					z = x + 10;

舉個(gè)例子,如在單例模式加鎖的雙重檢測(cè)中,需要在對(duì)象的前面加一個(gè)關(guān)鍵字 volatile,如果不加的話,在new對(duì)象的時(shí)候,會(huì)經(jīng)歷以下步驟:開辟內(nèi)存空間,堆內(nèi)存初始化,棧中對(duì)象指向堆中對(duì)象。這里就會(huì)出現(xiàn)一個(gè)問(wèn)題,由于new對(duì)象并沒(méi)有保證這個(gè)原子操作,因此就會(huì)出現(xiàn)指令重排的情況,就是可能會(huì)先指向堆中的對(duì)象,再在堆內(nèi)存中初始化,就是第二步和第三步的順序可能會(huì)發(fā)生改變。

public class SingletonTest{
    private volatile static SingletonTest instance = null;
    private SingletonTest() {}

    public static SingletonTest getInstance() {
            if (instance == null) {
                synchronized (SingletonTest.class) {
                    if (instance == null) {
                        //在不加volatile或者其他鎖的情況下
                        //可能會(huì)出現(xiàn)指令重排的情況
                        instance = new Singleton();
                    }
                }
            }
            return instance;
     }
}

那在多線程的情況下,在第一個(gè)線程正好執(zhí)行到發(fā)生指令重排的第二步,就是指向了一個(gè)堆中的對(duì)象,但還沒(méi)有初始化,只是經(jīng)歷了實(shí)例化,而第二個(gè)線程進(jìn)行第一個(gè)if判斷的時(shí)候,此時(shí)并沒(méi)有加鎖,所以發(fā)現(xiàn)不為null,就直接return了,但是return的是一個(gè)你有進(jìn)行初始化的一個(gè)值,因此返回的對(duì)象肯定是有問(wèn)題的

所以為了解決這個(gè)指令重排的問(wèn)題,就需要在這個(gè)對(duì)象上面加上volatile這個(gè)關(guān)鍵字了,這樣就能禁止指令重排了

private volatile static SingletonTest instance = null;

8,內(nèi)存屏障

在jvm和硬件層面都有實(shí)現(xiàn)內(nèi)存屏障的方式。

在jvm層面,在JSR規(guī)范中定義了四種內(nèi)存屏障,分別是LoadStore,LoadLoad,StoreLoad,StoreStore。Load操作可以當(dāng)做成是一個(gè)read讀取操作,Store操作可以當(dāng)做成是一個(gè)寫入操作,兩個(gè)操作之間相當(dāng)于加了一個(gè)一堵墻,從而保證兩個(gè)操作的順序不被打亂

LoadStore:在store2指令寫入數(shù)據(jù)之前,保證數(shù)據(jù)一定被load1指令先寫入進(jìn)去

LoadLoad:在Load2指令讀取數(shù)據(jù)之前,保證數(shù)據(jù)一定被load1指令先讀取出來(lái)

StoreLoad:在Load2指令讀取數(shù)據(jù)之前,保證數(shù)據(jù)一定被Store指令寫入進(jìn)去

StoreStore:在store2指令寫入數(shù)據(jù)之前,保證數(shù)據(jù)一定被load1指令讀取出來(lái)

并且以上的寫入操作,都是可以實(shí)現(xiàn)所有的處理器都可以感知到數(shù)據(jù)的變化,即保證可見性。當(dāng)前jvm底層實(shí)現(xiàn)內(nèi)存屏障的方式主要是通過(guò)這個(gè)StoreLoad方式來(lái)實(shí)現(xiàn)的。

在硬件層面,也提供了一系列的內(nèi)存屏障的方式保證數(shù)據(jù)的一致性,主要是通過(guò)ifence和sfence來(lái)實(shí)現(xiàn)讀寫屏障,也可以通過(guò)Lock前綴來(lái)實(shí)現(xiàn)這個(gè)類似于內(nèi)存屏障的功能。但是在JMM內(nèi)存模型中屏蔽了這種底層硬件帶來(lái)的差異,直接由JVM來(lái)為不同的平臺(tái)生成相應(yīng)的字節(jié)碼。通過(guò)內(nèi)存屏障的方式,來(lái)保證共享變量的有序性

9,為何多線程的累加值總是小于期待值

了解這個(gè)JMM的內(nèi)存模型之后,接下來(lái)通過(guò)之前的多線程的系列的文章,來(lái)對(duì)上述這個(gè)問(wèn)題做一個(gè)初步的了解。

count++;

由于在java中,實(shí)現(xiàn)線程的方式是使用的內(nèi)核態(tài)的方式實(shí)現(xiàn)的多線程,也就是說(shuō)開發(fā)者只能通過(guò)內(nèi)核去調(diào)用操作系統(tǒng),再去調(diào)用線程,因此開發(fā)人員并不能控制線程,因此就不能控制上下文切換等,并且實(shí)現(xiàn)線程的方式是搶占式的方式實(shí)現(xiàn),所以在累加操作中,某個(gè)值可能只執(zhí)行了一半,就出現(xiàn)了cpu中時(shí)間片的切換,導(dǎo)致這個(gè)值被其他線程操作,如果是在多線程的情況下,兩個(gè)線程同時(shí)操作一個(gè)值,就會(huì)出現(xiàn)這種值被覆蓋的問(wèn)題。因此最終出現(xiàn)的結(jié)果會(huì)小于期待值

其次是通過(guò)JMM模型可知,每個(gè)線程都有屬于自己的工作區(qū)間,但是每個(gè)線程在將值修改之后,其他線程并不能感知到,就是無(wú)法保證可見性的問(wèn)題,因此也會(huì)出現(xiàn)大量的值被覆蓋。所以累加的結(jié)構(gòu)也會(huì)小于期待值

因此需要通過(guò)加鎖的方式強(qiáng)行保證線程間執(zhí)行順序,以及需要通過(guò)實(shí)現(xiàn)內(nèi)存屏障的方式來(lái)實(shí)現(xiàn)線程間的可見性和有序性以及原子性。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-661302.html

到了這里,關(guān)于【JUC系列-01】深入理解JMM內(nèi)存模型的底層實(shí)現(xiàn)原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 深入理解并發(fā)編程藝術(shù)之內(nèi)存模型

    深入理解并發(fā)編程藝術(shù)之內(nèi)存模型

    隨著硬件技術(shù)的飛速發(fā)展,多核處理器已經(jīng)成為計(jì)算設(shè)備的標(biāo)配,這使得開發(fā)人員需要掌握并發(fā)編程的知識(shí)和技巧,以充分發(fā)揮多核處理器的潛力。然而并發(fā)編程并非易事,它涉及到許多復(fù)雜的概念和原理。為了更好地理解并發(fā)編程的內(nèi)在機(jī)制,需要深入研究?jī)?nèi)存模型及其在

    2024年02月14日
    瀏覽(25)
  • 了解JAVA內(nèi)存模型(JMM)

    我們常說(shuō)的JMM指的是Java內(nèi)存模型(Java Memory Model,JMM),主要用于控制Java程序解決線程間如何通信和數(shù)據(jù)同步,JMM規(guī)范了多線程訪問(wèn)共享內(nèi)存時(shí)的 可見性、有序性和原子性 。 所有的共享變量都存在 主內(nèi)存 中; 每個(gè)線程 都保存了一份該線程使用到的 共享變量的副本 。 如

    2024年02月06日
    瀏覽(30)
  • JMM(Java 內(nèi)存模型)詳解

    JMM(Java 內(nèi)存模型)詳解

    為什么要弄一個(gè) CPU 高速緩存(CPU Cauche)呢? 類比我們開發(fā)網(wǎng)站后臺(tái)系統(tǒng)使用的緩存(比如 Redis)是為了解決程序處理速度和訪問(wèn)常規(guī)關(guān)系型數(shù)據(jù)庫(kù)速度不對(duì)等的問(wèn)題。 CPU 緩存則是為了解決 CPU 處理速度和內(nèi)存處理速度不對(duì)等的問(wèn)題。 我們甚至可以把內(nèi)存可以看作外存的高

    2024年02月12日
    瀏覽(25)
  • JMM(Java內(nèi)存模型)詳解

    ? JMM 是Java內(nèi)存模型( Java Memory Model),簡(jiǎn)稱JMM。它本身只是一個(gè)抽象的概念,并不真實(shí)存在,它描述的是一種規(guī)則或規(guī)范,是和多線程相關(guān)的一組規(guī)范。通過(guò)這組規(guī)范,定義了程序中對(duì)各個(gè)變量(包括實(shí)例字段,靜態(tài)字段和構(gòu)成數(shù)組對(duì)象的元素)的訪問(wèn)方式。需要每個(gè)JVM

    2023年04月08日
    瀏覽(27)
  • 深入理解多線程編程和 JVM 內(nèi)存模型

    深入理解多線程編程和 JVM 內(nèi)存模型

    目錄 一、什么是多線程編程 二、JVM介紹 三、?JVM 內(nèi)存模型 多線程編程是一種編程方式,它允許程序在同一時(shí)間內(nèi)執(zhí)行多個(gè)線程或任務(wù)。線程是程序執(zhí)行的最小單位,多線程編程可以將任務(wù)拆分為多個(gè)線程,每個(gè)線程獨(dú)立執(zhí)行特定的操作或任務(wù)。 在傳統(tǒng)的單線程編程中,程

    2024年01月23日
    瀏覽(21)
  • 深入理解 Spark(四)Spark 內(nèi)存管理模型

    深入理解 Spark(四)Spark 內(nèi)存管理模型

    Executor 進(jìn)程作為一個(gè) JVM 進(jìn)程,其內(nèi)存管理建立在 JVM 的內(nèi)存管理之上,整個(gè)大致包含兩種方式:堆內(nèi)內(nèi)存和堆外內(nèi)存。 一個(gè) Executor 當(dāng)中的所有 Task 是共享堆內(nèi)內(nèi)存的。一個(gè) Work 中的多個(gè) Executor 中的多個(gè) Task 是共享堆外內(nèi)存的。 堆內(nèi)內(nèi)存和堆外內(nèi)存 大數(shù)據(jù)領(lǐng)域兩個(gè)比較常見

    2024年01月24日
    瀏覽(23)
  • 【netty系列-01】深入理解網(wǎng)絡(luò)通信基本原理和tcp/ip協(xié)議

    【netty系列-01】深入理解網(wǎng)絡(luò)通信基本原理和tcp/ip協(xié)議

    Netty系列整體欄目 內(nèi)容 鏈接地址 【一】深入理解網(wǎng)絡(luò)通信基本原理和tcp/ip協(xié)議 https://zhenghuisheng.blog.csdn.net/article/details/136359640 【二】深入理解Socket本質(zhì)和BIO https://zhenghuisheng.blog.csdn.net/article/details/136549478 在最初的網(wǎng)絡(luò)中,是借鑒于這個(gè)OSI七層網(wǎng)絡(luò)模型,而在實(shí)際開發(fā)應(yīng)用中

    2024年03月17日
    瀏覽(32)
  • [JVM] 淺談JMM(Java 內(nèi)存模型)

    Java 內(nèi)存模型(Java Memory Model,JMM)是 Java 虛擬機(jī)規(guī)范中定義的一種抽象計(jì)算機(jī)內(nèi)存模型,用于描述 Java 程序在多線程下的內(nèi)存訪問(wèn)行為。JMM 定義了線程之間共享變量的可見性和有序性規(guī)則,為開發(fā)者提供了一種可靠的同步機(jī)制,以避免并發(fā)程序中常見的線程安全問(wèn)題。 JMM

    2024年01月16日
    瀏覽(33)
  • Java內(nèi)存區(qū)域(運(yùn)行時(shí)數(shù)據(jù)區(qū)域)和內(nèi)存模型(JMM)

    Java內(nèi)存區(qū)域(運(yùn)行時(shí)數(shù)據(jù)區(qū)域)和內(nèi)存模型(JMM)

    Java?內(nèi)存區(qū)域和內(nèi)存模型是不一樣的東西,內(nèi)存區(qū)域是指 Jvm 運(yùn)行時(shí)將數(shù)據(jù)分區(qū)域存儲(chǔ),強(qiáng)調(diào)對(duì)內(nèi)存空間的劃分。 而內(nèi)存模型(Java Memory?Model,簡(jiǎn)稱 JMM )是定義了線程和主內(nèi)存之間的抽象關(guān)系,即 JMM 定義了 JVM 在計(jì)算機(jī)內(nèi)存(RAM)中的工作方式,如果我們要想深入了解Java并發(fā)

    2024年02月12日
    瀏覽(32)
  • 【jvm系列-06】深入理解對(duì)象的實(shí)例化、內(nèi)存布局和訪問(wèn)定位

    【jvm系列-06】深入理解對(duì)象的實(shí)例化、內(nèi)存布局和訪問(wèn)定位

    JVM系列整體欄目 內(nèi)容 鏈接地址 【一】初識(shí)虛擬機(jī)與java虛擬機(jī) https://blog.csdn.net/zhenghuishengq/article/details/129544460 【二】jvm的類加載子系統(tǒng)以及jclasslib的基本使用 https://blog.csdn.net/zhenghuishengq/article/details/129610963 【三】運(yùn)行時(shí)私有區(qū)域之虛擬機(jī)棧、程序計(jì)數(shù)器、本地方法棧 https

    2023年04月16日
    瀏覽(34)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包