Java中的關(guān)鍵字volatile詳解

volatile關(guān)鍵字經(jīng)常用來修飾變量。不過,volatile本身很容易被誤用。本篇就介紹一下volatile的原理和使用方式。

成都創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務,包含不限于成都網(wǎng)站設計、網(wǎng)站建設、圖木舒克網(wǎng)絡推廣、微信小程序開發(fā)、圖木舒克網(wǎng)絡營銷、圖木舒克企業(yè)策劃、圖木舒克品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務,您的肯定,是我們最大的嘉獎;成都創(chuàng)新互聯(lián)為所有大學生創(chuàng)業(yè)者提供圖木舒克建站搭建服務,24小時服務熱線:18982081108,官方網(wǎng)址:bm7419.com

在介紹volatile關(guān)鍵字原理前,我們首先要了解JVM運行時的內(nèi)存分配邏輯。

Java中的關(guān)鍵字volatile詳解

對于成員變量i,它存儲在堆內(nèi)存中。每個線程在運行時都會有一個自己的線程棧,線程如果要訪問類的成員變量i,會通過引用獲取到堆中變量i實際的值10,然后把這個變量值拷貝到自己的棧內(nèi)存中,作為一個變量副本,之后線程便不再會與堆中的變量有實際聯(lián)系。每個線程都有一個自己的本地副本,相互隔離。線程訪問自己棧內(nèi)存的效率比訪問堆的效率高。線程對變量i值的修改,只會修改自己線程副本中的值,修改結(jié)束后,在線程退出前,會把自己線程副本中的值,刷新到堆中。

保證內(nèi)存可見性

對于如下代碼:

public class VolatileTest implements Runnable{
  //volatile
  private static boolean flag = false;
  

  @Override
  public void run() {
    while (!flag){
      System.out.println(Thread.currentThread().getName() +"執(zhí)行中");
    }
    System.out.println(Thread.currentThread().getName() +"執(zhí)行完畢");
  }
  
  //main線程
  public static void main(String[] args) throws InterruptedException {
    new Thread(new VolatileTest(), "支線程Volatile").start();
    Thread.sleep(1000);
    flag = true;
  }

}

大多數(shù)時候可以正常中斷,但是一旦發(fā)送異常,便會導致線程死循環(huán)。所以需要在flag標志上加一個volatile關(guān)鍵字。對于加了volatile關(guān)鍵字的變量值,線程1修改了這個值的話,會強制將修改值直接寫入堆內(nèi)存中,其他線程各自線程棧中的變量副本無效,只能去堆中取最新的變量值。多個線程之間的內(nèi)存可見得以保證。
值得注意的是,volatile關(guān)鍵字不能保證原子性。

private volatile int i;

i++;

i ++ 這個操作涉及到獲取值,自增和賦值3部分。無法直接完成。上面想要以volatile來實現(xiàn)原子性的寫法是錯誤的。

禁止指令重排

現(xiàn)代JVM對代碼的執(zhí)行順序有一定的優(yōu)化。例如:

int a = 4;
int b = 5;
int c = a + b; 

上面3條指令進過JVM優(yōu)化以后,時間的執(zhí)行順序不一定是從上到下,有可能是 第二條--->第一條-->第三條??傊粫绊懽罱K執(zhí)行結(jié)果。

但是在多線程情況下,如下代碼就會有風險:

//線程1:
context = loadContext();  
inited = true;       
 
//線程2:
while(!inited ){
 
}
doSomething(context);

線程1的兩條語句之間沒有依賴性,經(jīng)過指令重排后,有可能inited置為true以后,context還沒有初始化。線程2發(fā)現(xiàn)inited為true,以為初始化完成,結(jié)束循環(huán),用時間還沒有初始化的context去執(zhí)行doSomething()方法。報錯。所以我們可以用volatile關(guān)鍵字修飾inited,保證context初始化。

以上所述是小編給大家介紹的Java中的關(guān)鍵字volatile詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對創(chuàng)新互聯(lián)網(wǎng)站的支持!

當前文章:Java中的關(guān)鍵字volatile詳解
文章路徑:http://bm7419.com/article40/jdgoeo.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供自適應網(wǎng)站、品牌網(wǎng)站建設網(wǎng)站維護、手機網(wǎng)站建設、網(wǎng)站導航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名