多線程中對static和volatile的理解

問題來源於編碼規範的一個例子html


一. 關於server模式下的主存和工做內存  
規則40     多線程訪問同一個可變變量,需增長同步機制
說明:根據Java Language Specification中對Java內存模型的定義, JVM中存在一個主內存(Java Heap Memory),Java中全部變量都儲存在主存中,對於全部線程都是共享的。每一個線程都有本身的工做內存(Working Memory),工做內存中保存的是主存中某些變量的拷貝,線程對全部變量的操做都是在工做內存中進行,線程之間沒法相互直接訪問,變量傳遞均須要經過主存完成。根據上述內存模型的定義,要在多個線程間安全的同步共享數據就必須使用鎖機制,將某線程中更新的數據從其工做內存中刷新至主內存,並確保其餘線程從主內存獲取此數據更新後的值再使用。
示例:
     很差:下面的代碼中,沒有對可變數據stopRequested的訪問作同步。程序指望在一秒鐘後線程能中止。但在用java 1.6的server模式運行此程序(Java –server StopThread)時,程序陷入死循環,不能結束。
public class StopThread 
{
    private static boolean stopRequested;

    public static void main(String[] args) throws InterruptedException 
{
        Thread backgroundThread = new Thread(new Runnable() 
{
            public void run() 
{
                int i = 0;
                while (!stopRequested)
{
                    i++;
                     }
            }
        });

        backgroundThread.start();

        TimeUnit.SECONDS.sleep(1);
        stopRequested = true;
    }
}

 

     
 
這裏爲何會陷入死循環,永遠不會中止呢?
參考兩篇文章
http://m.blog.csdn.net/blog/lyy5682077/17588155
http://www.cnblogs.com/trytocatch/archive/2013/01/07/2850002.html
JIT或HotSpot編譯器在server模式和client模式編譯不一樣,server模式爲了使線程運行更快,若是其中一個線程更改了變量boolean flag 的值,那麼另一個線程會看不到,由於另一個線程爲了使得運行更快因此從寄存器或者本地cache中取值,而不是從內存中取值,那麼使用volatile後,就告訴不管是什麼線程,被volatile修飾的變量都要從內存中取值。《內存柵欄》
 
java在server模式下,各個線程使用各自的工做內存,一個線程改變了變量的值,另一個線程並不會從主存中取
 
上面例子中的問題,變量 stopRequested前加上volatile能夠解決:
增長了  synchronized 同步機制後,程序就能正確地在  1 秒後終止。另外一個方案是在變量前增長      volatile  關鍵字。
public class StopThread 
{
    private static boolean stopRequested;
    
    private static synchronized void requestStop() 
{
        stopRequested = true;
    }
    
    private static synchronized boolean isStopRequested() 
{
        return stopRequested;
    }

    public static void main(String[] args) throws InterruptedException 
{
        Thread backgroundThread = new Thread(new Runnable() 
{
            public void run() 
{
                int i = 0;
                while (!isStopRequested()) 
{
                    i++;
                     }
            }
        });

        backgroundThread.start();

        TimeUnit.SECONDS.sleep(1);
        requestStop();
    }
}

 

 
二. static和volatile的區別
參考http://blog.sina.com.cn/s/blog_4e1e357d0101i486.html
1. volatile是告訴編譯器,每次取這個變量的值都須要從主存中取,而不是用本身線程工做內存中的緩存.
2. static 是說這個變量,在主存中全部此類的實例用的是同一份,各個線程建立時須要從主存同一個位置拷貝到本身工做內存中去(而不是拷貝此類不一樣實例中的這個變量的值),也就是說只能保證線程建立時,變量的值是相同來源的,運行時仍是使用各自工做內存中的值,依然會有不一樣步的問題.
相關文章
相關標籤/搜索