关键字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的同步机制都是围绕原子性和可见性两个方面来确保线程安全的。