Java多線程學習(四)——volatile關鍵字

volatile關鍵字

當用volatile關鍵字聲明變量的時候,就等於告訴虛擬機,這個變量極有可能被某些程序或者線程修改,爲了保證比那輛被修改後應用程序範圍內的全部線程能夠看到這個改動,虛擬機必須採用一些方法保證這個變量的可見性。java

volatile與死循環

public class PrintString {
    private boolean isContinue = true;

    public boolean isContinue() {
        return isContinue;
    }

    public void setContinue(boolean aContinue) {
        this.isContinue = aContinue;
    }

    public void printStringFunc(){
        try {
            while (isContinue){
                System.out.println("run printStringFunc threadName=" + Thread.currentThread().getName());
                Thread.sleep(1000);
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args){
        PrintString printString = new PrintString();
        printString.printStringFunc();
        System.out.println("stop printStringFunc stopThread=" + Thread.currentThread().getName());
        printString.setContinue(false);
    }
}
複製代碼
run printStringFunc threadName=main
run printStringFunc threadName=main
run printStringFunc threadName=main
run printStringFunc threadName=main
run printStringFunc threadName=main
run printStringFunc threadName=main
run printStringFunc threadName=main
run printStringFunc threadName=main
...
複製代碼

上面的代碼執行後會一直運行沒法停下來,下面來看看解決方法。git

public class PringStringThread {

    private boolean isContinue = true;

    public boolean isContinue() {
        return isContinue;
    }

    public void setContinue(boolean aContinue) {
        this.isContinue = aContinue;
    }

    public void printStringFunc(){
        try {
            while (isContinue){
                System.out.println("run printStringFunc threadName=" + Thread.currentThread().getName());
                Thread.sleep(1000);
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }


}

public static void main(String[] args){

        PringStringThread pringStringThread = new PringStringThread();
        new Thread(() -> pringStringThread.printStringFunc()).start();
        try {
            Thread.sleep(2000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        pringStringThread.setContinue(false);

    }
複製代碼
run printStringFunc threadName=Thread-0
run printStringFunc threadName=Thread-0

Process finished with exit code 0
複製代碼

能夠發現線程退出循環了。github

volatile關鍵字與synchronized比較

  1. volatile關鍵字是線程同步的輕量級實現,因此volatile性能確定比synchronized關鍵字要好。可是volatile關鍵字只能用於變量而synchronized關鍵字能夠修飾方法以及代碼塊。synchronized關鍵字在jdk6以後進行了主要包括爲了減小得到鎖和釋放鎖帶來的性能消耗而引入的偏向鎖和輕量級鎖以及其它各類優化以後執行效率有了顯著提高,實際開發中使用synchronized關鍵字仍是更多一些。
  2. 多線程訪問volatile關鍵字不會發生阻塞,而synchronized關鍵字可能會發生阻塞。
  3. volatile關鍵字能保證數據的可見性,但不能保證數據的原子性。synchronized關鍵字二者都能保證。
  4. volatile關鍵字用於解決變量在多個線程之間的可見性,而synchronized關鍵字解決的是多個線程之間訪問資源的同步性。

本節代碼Githubbash


歡迎關注公衆號: 微信

公衆號微信
相關文章
相關標籤/搜索