關鍵字volatile的主要作用是使變量在多線程間可見。
解決異步死循環
如下代碼
public class RunThread extends Thread {
//volatile private boolean isRunning=true;
private boolean isRunning=true;
public boolean isRunning(){
return isRunning;
}
public void setRunning(boolean isRunning){
this.isRunning=isRunning;
}
@Override
public void run(){
System.out.println("進入run了");
while (isRunning==true){
}
System.out.println("線程被停止了");
}
}
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
RunThread thread= new RunThread();
thread.start();
Thread.sleep(1000);
thread.setRunning(false);
System.out.println("已經賦值false");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
運行效果
即代碼無法運行到“線程被停止了”
解決辦法:將RunThread類中volatile private boolean isRunning=true;取消註釋,並註釋private boolean isRunning=true;
即可出現如下效果
我們再看下出現上面的死循環的原因之前我們先看下線程的私有堆棧的結構圖:
上面代碼出現死鎖的原因就是當主內存的值修改後,但是工作內存的值已經加載,所以工作內存的值不會發生改變,私有堆棧中的值和公共堆棧中的值不同步造成的。
然後再看下關鍵字volatile是如何解決死循環的。
上圖表示,通過使用volatile關鍵字,強制的從公共內存中讀取變量的值。
關鍵字synchronized和volatile比較
1)volatile是線程同步的輕量級實現,所以性能要比synchronized要好,並且volatile只修飾於變量,而synchronized可以修飾方法以及代碼塊。並且jdk新版本的發佈,synchronized關鍵字在執行效率上得到很大提升,在開發中使用synchronized關鍵字的比率還是比較大的。
2)多線程訪問volatile不會發生阻塞,而synchronized會出現阻塞。
3)volatile能保證數據的可見性,但是不能保證原子性;而synchronized可以保證原子性,也可以間接的保證可見性,因爲它將私有內存和公共內存中的數據做同步。
4)volatile解決的是變量在多個線程之間的可見性,而synchronized解決的是多個線程之間訪問資源的同步性。java的同步機制都是圍繞原子性和可見性兩個方面來確保線程安全的。