溫馨提示×

溫馨提示×

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

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

Java?volatile關(guān)鍵字的特性是什么

發(fā)布時間:2022-12-13 09:15:29 來源:億速云 閱讀:109 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“Java volatile關(guān)鍵字的特性是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Java volatile關(guān)鍵字的特性是什么”吧!

一、概述

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

volatile是Java虛擬機提供的輕量級的同步機制,它有三個特性:

(1)保證可見性

(2)不保證原子性

(3)禁止指令重排

二、特性詳解

volatile保證可見性

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

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

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

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

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

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

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

舉例說明:

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

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

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

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

無可見性代碼演示:

@Test
public void test1() {
    DataDemo dataDemo = new DataDemo();
    RunThread runThread = new RunThread(dataDemo);
    runThread.start();
    while (dataDemo.getNumber() == 0) {
    }
    System.out.println("具有可見性驗證通過");
}
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

Java?volatile關(guān)鍵字的特性是什么

結(jié)果分析:

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

原理說明:

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

Java?volatile關(guān)鍵字的特性是什么

可見性代碼演示:

@Test
public void test1() {
    DataDemo dataDemo = new DataDemo();
    RunThread runThread = new RunThread(dataDemo);
    runThread.start();
    while (dataDemo.getNumber() == 0) {
    }
    System.out.println("具有可見性驗證通過");
}
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
具有可見性驗證通過

結(jié)果分析:

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

原理說明:

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

Java?volatile關(guān)鍵字的特性是什么

感謝各位的閱讀,以上就是“Java volatile關(guān)鍵字的特性是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Java volatile關(guān)鍵字的特性是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細節(jié)

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

AI