Java 多線程:volatile關鍵字

概念


volatile 也是多線程的解決方案之一。**volatile 可以保證可見性,可是不能保證原子性。**它只能做用於變量,不能做用於方法。當一個變量被聲明爲 volatile 的時候,任何對該變量的讀寫都會繞太高速緩存,直接讀取主內存的變量的值。緩存

如何理解直接讀寫主內存的值:回到 多線程生成的緣由(Java內存模型與i++操做解析) ,在 i++ 操做的時候,當 進行 執行引擎 對 變量 進行 + 1 以後,原來 是應該寫入到 本地內存中,再由本地內存寫入到主內存中,可是 因爲 變量使用了 volatile 的修飾,因此 該值不會通過本地內存,而是直接寫入到 主內存中去。 讀取也是一樣的道理。多線程

使用volatile 有兩點須要注意的地方:線程

  • 運算結果並不依賴於當前值,或者能確保只有單一的線程可以修改變量的值。
  • 變量不須要和其餘的狀態變量共同參與不變約束

對於第一點的理解:

public class Test {
    public static volatile int i = 0;
    public static void main(String args[]){

        new Thread(new Runnable(){
            public void run(){
                for(int j = 0; j < 10000; j++)
                    i++;
                System.out.println("Thread1 end...");
            }
        }).start();

        new Thread(new Runnable(){
            public void run(){
                for(int j = 0; j < 10000; j++)
                    i++;
                System.out.println("Thread2 end...");
            }
        }).start(); 

        i++;

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("i = " + i);
    }
}

對於第二點的理解:

private Date start;      
private Date end;      

public void setInterval(Date newStart, Date newEnd) {      
    // 檢查start<end是否成立, 在給start賦值以前不變式是有效的      
    start = newStart;      

    // 可是若是另外的線程在給start賦值以後給end賦值以前時檢查start<end, 該不變式是無效的      

    end = newEnd;      
    // 給end賦值以後start<end不變式從新變爲有效      
}

最後,關於何時使用 volatile,通常是用來當作標記來使用。好比說,當shutdown() 方法被調用的時候,全部的 doWork() 方法都會停下來。code

相關文章
相關標籤/搜索