1. 程式人生 > 實用技巧 >Matplotlib基礎繪圖

Matplotlib基礎繪圖

在講解volatile關鍵字的時候,我們先看一個簡單的例子:

package SynchronizedCass;

public class t4 {
    public static void main(String[] args) {
        try {
            RunThread thread = new RunThread();
            thread.start();
            Thread.sleep(1000);
            thread.setRunning(false);
            System.out.println(
"已經被賦值為false"); } catch (InterruptedException e) { // TODO 自動生成的 catch 塊 e.printStackTrace(); } } } class RunThread extends Thread { private boolean isRunning = true; public boolean isRunning() { return isRunning; } public
void setRunning(boolean isRunning) { this.isRunning = isRunning; } @Override public void run() { super.run(); System.out.println("進入run方法了"); while(isRunning == true) { //無限迴圈 } System.out.println("執行緒被停止了!"); } }
進入run方法了
已經被賦值為false

從結果上看:System.out.println("執行緒被停止了!"); 這句程式碼從未被執行,程式進入了死迴圈,這是為什麼呢?

啟動執行緒後private boolean isRunning = true; 變數存在於記憶體的公共堆疊及執行緒的私有堆疊中。在JVM被設定為-server模式時為了執行緒執行的效率。執行緒一直在私有堆疊中取得isRunning的值是true;雖然程式碼thread.setRunning(false)被執行了,更新的卻是公共堆疊中的isRunning變數值false,執行緒的私有堆疊中任為true,所以執行緒thread就一直處於死迴圈的狀態。

這個問題就是公共堆疊中的值和私有堆疊中的值不同步造成的。那麼如何解決這個問題,這就到了我們今天要介紹的關鍵字volatile,當他修飾isRunning變數時,強制性地從公共堆疊中進行取值。

package SynchronizedCass;

public class t4 {
    public static void main(String[] args) {
        try {
            RunThread thread = new RunThread();
            thread.start();
            Thread.sleep(1000);
            thread.setRunning(false);
            System.out.println("已經被賦值為false");
        } catch (InterruptedException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
    }
}

class RunThread extends Thread    {
    volatile private boolean isRunning = true;
    
    public boolean isRunning() {
        return isRunning;
    }
    
    public void setRunning(boolean isRunning) {
        this.isRunning = isRunning;
    }
    
    @Override
    public void run() {
        super.run();
        System.out.println("進入run方法了");
        while(isRunning == true) {
            //無限迴圈
        }
        System.out.println("執行緒被停止了!");
    }
}
進入run方法了
已經被賦值為false
執行緒被停止了!

我們看一下使用volatile關鍵字後發生了什麼?

執行緒主體是不是強制地從公共記憶體中讀取變數的值,它增加了例項變數在多個執行緒之間的可見性。

比較一下關鍵字volatile和synchronized,如下:

  • 關鍵字volatile解決的是變數在多個執行緒之間的可見性;而synchronized關鍵字解決的是多個執行緒之間的訪問資源同步性
  • 關鍵字volatile只能用於修飾變數,而synchronized可以修飾方法,以及程式碼塊。
  • 多執行緒訪問volatile不會發生阻塞,而synchronized會發生阻塞。
  • volatile能保證資料的可見性,但是不能保證原子性;而synchronized可以保證原子性,也間接保證可見性(因為他會將私有記憶體和公共記憶體中的資料做同步)