JAVA多線程可見性


  為了更清楚的了解可見性,這里先介紹一下jmm。jmm並非是一個組件或者程序,他是抽象計算機內存模型的一組規則、規范,定義了變量訪問內存的方式。

 

如圖:

  jmm的每個線程有獨立的工作內存,他們的工作方式是從主內存將變量讀取到自己的工作內存,然后在工作內存中進行邏輯或者自述運算再把變量寫回到主內存中。正常情況下各線程的工作內存之間是相互隔離的、不可見的。

有這樣一個場景,兩個小孩子玩游戲,游戲內容是A小孩跳繩,B小孩叫停。
代碼示例1:
public class Game {
private volatile boolean stop = false;

public void stop() {
this.stop = true;
String name = Thread.currentThread().getName();
System.out.println(name + "小孩叫停: ");
}

public void ropeSkipping() {
String name = Thread.currentThread().getName();
int i = 0;
for (;!this.stop;i++) {

}
System.out.println(name + "小孩跳了: " + i + "次");
}

public class Play {
public static void main(String[] args) {
Game game = new Game();
Thread childB = new Thread(()->{
game.stop();
},"childB");

Thread childA = new Thread(()->{
game.ropeSkipping();
},"childA");
//讓A先跳
childA.start();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
childB.start();
}
}

如果沒有volatile關鍵字,線程childB執行了stop方法線程childA也是不會停下來的。volatile的作用保證了變量在不同線程間的可見性。

代碼示例2:
public class Game {
private boolean stop = false;

public void stop() {
this.stop = true;
String name = Thread.currentThread().getName();
System.out.println(name + "小孩叫停: ");
}

public void ropeSkipping() {
String name = Thread.currentThread().getName();
int i = 0;
for (;!this.stop;i++) {

System.out.println(name + "小孩跳了: " + i + "次");

}
}

示例2去掉了volatile關鍵字,把System.out.println輸出語句放入了循環中,線程childB執行了stop方法線程childA會停下來,因為System.out.println里面有包含了synchronized關鍵字,synchronized也有讓線程間可見性的作用。

除此之外,final關鍵字也能讓變量(常量)線程可見,就不一一舉例了。

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM