亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java volatile關(guān)鍵字特性講解上篇

 更新時(shí)間:2022年12月12日 15:52:09   作者:愛吃南瓜糕的北絡(luò)  
JMM要求保證可見性、原子性、有序性,volatile可以保證其中的兩個(gè),本篇文章具體驗(yàn)證volatile的可見性,不原子性和禁重排,同時(shí)解決volatile的不保證原子性,讓代碼具有原子性

一、概述

volatile是Java中的關(guān)鍵字,用來(lái)修飾會(huì)被不同線程訪問(wèn)和修改的變量。

volatile是Java虛擬機(jī)提供的輕量級(jí)的同步機(jī)制,它有三個(gè)特性:

(1)保證可見性

(2)不保證原子性

(3)禁止指令重排

二、特性詳解

volatile保證可見性

Java內(nèi)存模型(JMM)定義了一組規(guī)則、規(guī)范,規(guī)定了程序中各個(gè)變量的訪問(wèn)方法。JMM關(guān)于同步的規(guī)定:

(1)線程解鎖前,必須把共享變量的值刷新回主內(nèi)存;

(2)線程加鎖前,必須讀取主內(nèi)存的最新值同步到自己的工作內(nèi)存;

(3)加鎖解鎖必須是同一把鎖;

說(shuō)明:由于JVM運(yùn)行程序的實(shí)體是線程,創(chuàng)建每個(gè)線程時(shí),JMM會(huì)為其創(chuàng)建一個(gè)工作內(nèi)存(也稱棧空間),工作內(nèi)存是每個(gè)線程的私有數(shù)據(jù)區(qū)域。

Java內(nèi)存模型規(guī)定所有變量都存儲(chǔ)在主內(nèi)存,主內(nèi)存是共享內(nèi)存區(qū)域,所有線程都可以訪問(wèn)。

但是線程對(duì)變量的操作(讀取、賦值等)必須在工作內(nèi)存中進(jìn)行。因此首先要將變量從主內(nèi)存拷貝到自己的工作內(nèi)存,然后對(duì)變量進(jìn)行操作,操作完成后再將變量寫會(huì)主內(nèi)存中。

舉例說(shuō)明:

(1)火車票賣票系統(tǒng)還剩下一張票,并已經(jīng)刷入到主內(nèi)存中:ticketNum = 1;

(2)此時(shí)有3個(gè)用戶在同時(shí)購(gòu)買票,3個(gè)線程都讀入了目前的票數(shù),ticketNum=1,那么線程就會(huì)繼續(xù)進(jìn)入購(gòu)買流程。

(3)假設(shè)其中一個(gè)線程先搶占了CPU資源,先買到票,并將自己的工作內(nèi)存中的ticketNum值改為0,ticketNum=0,然后再寫回到主內(nèi)存。

這時(shí),由于一個(gè)線程的用戶已經(jīng)買到了票,那么其他用戶的線程應(yīng)該不能再繼續(xù)進(jìn)入購(gòu)買票的流程了,因此需要系統(tǒng)通知到其他線程 ticketNum=0 這個(gè)消息。如果可以達(dá)到這樣的效果,可以理解為 具有可見性。

無(wú)可見性代碼演示:

@Test
public void test1() {
    DataDemo dataDemo = new DataDemo();
    RunThread runThread = new RunThread(dataDemo);
    runThread.start();
    while (dataDemo.getNumber() == 0) {
    }
    System.out.println("具有可見性驗(yàn)證通過(guò)");
}
public class DataDemo {
    private int number = 0;
    public void add() {
        this.number = this.number + 10;
    }
    public int getNumber() {
        return number;
    }
}
public class RunThread extends Thread {
    private DataDemo dataDemo;
    public RunThread(DataDemo dataDemo) {
        this.dataDemo = dataDemo;
    }
    @Override
    public void run() {
        System.out.println("線程[" + Thread.currentThread().getName() + "] 正在執(zhí)行");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        dataDemo.add();
        System.out.println("線程[" + Thread.currentThread().getName() + "]更新后,number值為:" + dataDemo.getNumber());
    }
}

執(zhí)行結(jié)果:
線程[Thread-0] 正在執(zhí)行
線程[Thread-0]更新后,number值為:10

結(jié)果分析:

可以看出子線程啟動(dòng)后將number值改為了10,雖然已經(jīng)改為了非0,但是主線程仍然一直處于while循環(huán)中,因此此時(shí)number不具有可見性,系統(tǒng)不會(huì)主動(dòng)通知主線程number值修改。

原理說(shuō)明:

這個(gè)問(wèn)題其實(shí)就是私有堆棧中的值和公共堆棧中的值不同步造成的。解決這樣的問(wèn)題就要使用 volatile 關(guān)鍵字了,它主要的作用就是當(dāng)線程訪問(wèn)number這個(gè)變量時(shí),強(qiáng)制性從公共堆棧中進(jìn)行取值。

可見性代碼演示:

@Test
public void test1() {
    DataDemo dataDemo = new DataDemo();
    RunThread runThread = new RunThread(dataDemo);
    runThread.start();
    while (dataDemo.getNumber() == 0) {
    }
    System.out.println("具有可見性驗(yàn)證通過(guò)");
}
public class DataDemo {
    // 給變量 number 添加 volatile 關(guān)鍵字修飾
    volatile private int number = 0;
    public void add() {
        this.number = this.number + 10;
    }
    public int getNumber() {
        return number;
    }
}
public class RunThread extends Thread {
    private DataDemo dataDemo;
    public RunThread(DataDemo dataDemo) {
        this.dataDemo = dataDemo;
    }
    @Override
    public void run() {
        System.out.println("線程[" + Thread.currentThread().getName() + "] 正在執(zhí)行");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        dataDemo.add();
        System.out.println("線程[" + Thread.currentThread().getName() + "]更新后,number值為:" + dataDemo.getNumber());
    }
}

執(zhí)行結(jié)果:
線程[Thread-0] 正在執(zhí)行
線程[Thread-0]更新后,number值為:10
具有可見性驗(yàn)證通過(guò)

結(jié)果分析:

通過(guò)對(duì)變量number變量添加了volatile關(guān)鍵字修飾,可以看出子線程啟動(dòng)后將number值改為了10,隨后主線程跳出了while循環(huán),輸出了“具有可見性驗(yàn)證通過(guò)”,說(shuō)明此時(shí)number具有可見性。

原理說(shuō)明:

通過(guò)使用 volatile 關(guān)鍵字,強(qiáng)制從公共內(nèi)存中讀取變量的值,內(nèi)存結(jié)構(gòu)如圖:

到此這篇關(guān)于Java volatile關(guān)鍵字特性講解上篇的文章就介紹到這了,更多相關(guān)Java volatile內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中的轉(zhuǎn)換流InputStreamReader解讀

    Java中的轉(zhuǎn)換流InputStreamReader解讀

    InputStreamReader是Java.io包中的一個(gè)類,用于將字節(jié)輸入流轉(zhuǎn)換為字符輸入流,它繼承自java.io.Reader類,提供了兩種構(gòu)造方法,可以使用默認(rèn)或指定字符集創(chuàng)建實(shí)例,常用方法包括讀取字符、判斷是否準(zhǔn)備好讀取數(shù)據(jù)和關(guān)閉流
    2024-09-09
  • Java中Integer的parseInt和valueOf的區(qū)別詳解

    Java中Integer的parseInt和valueOf的區(qū)別詳解

    這篇文章主要介紹了Java中Integer的parseInt和valueOf的區(qū)別詳解,nteger.parseInt(s)是把字符串解析成int基本類型,Integer.valueOf(s)是把字符串解析成Integer對(duì)象類型,其實(shí)int就是Integer解包裝,Integer就是int的包裝,需要的朋友可以參考下
    2023-11-11
  • SpringBoot?Security使用MySQL實(shí)現(xiàn)驗(yàn)證與權(quán)限管理

    SpringBoot?Security使用MySQL實(shí)現(xiàn)驗(yàn)證與權(quán)限管理

    安全管理是軟件系統(tǒng)必不可少的的功能。根據(jù)經(jīng)典的“墨菲定律”——凡是可能,總會(huì)發(fā)生。如果系統(tǒng)存在安全隱患,最終必然會(huì)出現(xiàn)問(wèn)題,這篇文章主要介紹了SpringBoot安全管理Spring?Security基本配置
    2022-11-11
  • 超詳細(xì)講解SpringCloud?Commons公共抽象的用法

    超詳細(xì)講解SpringCloud?Commons公共抽象的用法

    這篇文章主要介紹了超詳細(xì)講解SpringCloud?Commons公共抽象的用法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Java不用算數(shù)運(yùn)算符來(lái)實(shí)現(xiàn)求和方法

    Java不用算數(shù)運(yùn)算符來(lái)實(shí)現(xiàn)求和方法

    我們都知道,Java的運(yùn)算符除了具有優(yōu)先級(jí)之外,還有一個(gè)結(jié)合性的特點(diǎn)。當(dāng)一個(gè)表達(dá)式中出現(xiàn)多種運(yùn)算符時(shí),執(zhí)行的先后順序不僅要遵守運(yùn)算符優(yōu)先級(jí)別的規(guī)定,還要受運(yùn)算符結(jié)合性的約束,以便確定是自左向右進(jìn)行運(yùn)算還是自右向左進(jìn)行運(yùn)算,但是如果不用運(yùn)算符怎么求和呢
    2022-04-04
  • mybatis-plus支持null字段全量更新的兩種方法

    mybatis-plus支持null字段全量更新的兩種方法

    本文主要介紹了mybatis-plus支持null字段全量更新的兩種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • 文件上傳SpringBoot后端MultipartFile參數(shù)報(bào)空問(wèn)題的解決辦法

    文件上傳SpringBoot后端MultipartFile參數(shù)報(bào)空問(wèn)題的解決辦法

    這篇文章主要介紹了文件上傳SpringBoot后端MultipartFile參數(shù)報(bào)空問(wèn)題的解決辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • SpringBoot通過(guò)注解注入Bean的幾種方式解析

    SpringBoot通過(guò)注解注入Bean的幾種方式解析

    這篇文章主要為大家介紹了SpringBoot注入Bean的幾種方式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-03-03
  • springboot結(jié)合mysql主從來(lái)實(shí)現(xiàn)讀寫分離的方法示例

    springboot結(jié)合mysql主從來(lái)實(shí)現(xiàn)讀寫分離的方法示例

    這篇文章主要介紹了springboot結(jié)合mysql主從來(lái)實(shí)現(xiàn)讀寫分離的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Java讀取并下載網(wǎng)絡(luò)文件的方法

    Java讀取并下載網(wǎng)絡(luò)文件的方法

    這篇文章主要為大家詳細(xì)介紹了Java讀取并下載網(wǎng)絡(luò)文件的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08

最新評(píng)論