2012-05-01 30 views

回答

4

volatile修飾符會告訴JVM對併發運行的線程保持謹慎。本質上,volatile用於指示變量的值將被不同的線程修改。

聲明揮發性Java變量是指:

  • 這個變量的值將不會被線程本地緩存:所有讀取和寫入將直接進入「主內存」

  • 訪問該變量就像封裝在一個同步塊中一樣,自身同步。

我們說「的行爲如同」第二點,因爲程序員至少(可能在大多數JVM實現)不涉及實際鎖定的對象。


揮發性修飾符告訴揮發性修改的變量可以通過程序的其他部分意外更改的編譯器。其中一種情況涉及多線程程序。

在多線程程序中,有時兩個或更多線程共享相同的實例變量。出於效率方面的考慮,每個線程都可以保留自己的這種共享變量的私有副本。

變量的實際副本(或主副本)在不同時間更新,例如輸入同步方法時。雖然這種方法運作良好,但有時可能效率不高。在某些情況下,真正重要的是變量的主副本始終反映其當前狀態。

爲了確保這一點,只需將變量指定爲volatile,即告訴編譯器必須始終使用volatile變量的主副本(或者至少始終保留任何私有副本與主副本保持一致,反之亦然)。此外,訪問主變量必須按照在任何私人副本上執行的精確順序執行。

+0

「對變量的訪問就好像它被包含在同步塊中一樣,同步於自身。」 < - 這聽起來像'myVolatile ++'似乎是'synchronized(something){myVolatile ++}',事實並非如此。 – yshavit

+0

這只是程序員的一個提示......不涉及鎖定...... –

+0

所以如果使用多線程的volatile修飾符,將不會保留變量的線程本地副本? –

4

(這個回答假設的Java 5+ - 在這之前,volatile有較弱的保證。)

當你想確保內存屏障這是非常有用,又名正式「之前發生」的關係,寫之間到一個字段,然後通過一個單獨的線程讀取到該字段。同步還可以爲您提供這種關係以及其他多線程保證,但速度稍慢,可能會造成同步瓶頸。

一個用例是在併發集合類(如ConcurrentHashMap,或LinkedBlockingQueue),其中,在與東西像原子的比較和集聯(CAS)操作,您可以編寫正確的線程安全的代碼,而不必使用​​。

+0

你可以請提一下你在說什麼回答 – Edge

+0

@Edge我的回答。它(我的答案)對於Java 1.4及更低版本是不正確的,因爲這裏沒有'volatile'發生的發生前關係。 – yshavit

1

volatile modifier告訴compiler由volatile修改的variable可以被程序的其他部分意外地改變。 其中一種情況涉及多線程程序。
在多線程程序中,有時兩個或多個threads共享相同的instance variable。出於效率考慮,每個thread都可以保留其自己的私有副本(in cache)。 variable的實際(或主要)副本(in ram)會在不同時間更新,例如輸入synchronized method時。
儘管此方法正常工作,但有時可能效率不高。在某些情況下,真正重要的是變量的主副本始終反映其當前狀態。爲了確保這一點,只需指定variable as volatile,它告訴compiler它必須始終使用volatile variable的主副本(不會保留緩存)。此外,訪問主變量必須按照在任何私人副本上執行的精確順序執行。
EX ...

public class snippet1 implements Runnable{ 
volatile int num =0; 

public void run(){ 
    Thread t = Thread.currentThread(); 
    String name = t.getName(); 
    if(name.equals("Thread1")){ 
     num=10; 
    } 
    else{ 
     System.out.println("value of num is :"+num); 
    } 

} 
public static void main(String args[]) throws InterruptedException{ 
    Runnable r = new snippet1(); 
    Thread t1 = new Thread(r); 
    t1.setName("Thread1"); 
    t1.start(); 

    Thread.sleep(1000); 

    Thread t2 = new Thread(r); 
    t2.setName("Thread2"); 
    t2.start(); 
} 

}

在上面的例子中,如果你不使用揮發性然後第二個線程的輸出可以是0
但如果ü把揮發性了它給你u擔保的價值應該是10 ..

1

你有第一個問題的好答案。第二個:

任何一個可以給我的是實時場景

IMO,你永遠也不會你揮發。有更好的多線程應用程序工具。這樣的高級語言有這個關鍵字有點奇怪。 Here是一個很好的閱讀(這是關於C#,但Java在這方面是相似的)。

+0

這是一個非常有用的答案! +1 –

3

如果您正在使用多線程編程,volatile關鍵字會更有用。當多個線程使用同一個變量時,每個線程將擁有自己的該變量的本地緩存副本。所以,當更新值爲 時,它實際上在本地緩存中更新,而不是在主變量內存中更新。 使用相同變量的另一個線程不知道另一個線程更改的值。爲了避免這個問題,如果你聲明一個變量爲volatile,那麼它將不會被存儲在本地緩存中。只要線程正在更新 值,它就會更新到主內存。所以,其他線程可以訪問更新的值。

聲明變量揮發性手段

  • 將沒有保持高速緩存是指在主存儲器的所有更改。
  • 對此變量的訪問作爲同步塊,即使它處於同步單元。

實施例 -

public class Snippet implements Runnable{ 
volatile int num =0; 

public void run(){ 
    Thread t = Thread.currentThread(); 
    String name = t.getName(); 
    if(name.equals("Thread1")){ 
     num=10; 
    } 
    else{ 
     System.out.println("value of num is :"+num); 
    } 

} 
public static void main(String args[]) throws InterruptedException{ 
    Runnable r = new Snippet(); 
    Thread t1 = new Thread(r); 
    t1.setName("Thread1"); 
    t1.start(); 

    Thread.sleep(1000); 

    Thread t2 = new Thread(r); 
    t2.setName("Thread2"); 
    t2.start(); 
} 
}