您的位置:首页 > 编程语言 > Java开发

JAVA多线程-对象及变量的并发访问(二)volatile关键字

2016-02-20 10:51 926 查看
三、Volatile关键字

    关键字volatile的主要作用是使变量在多个线程间可见。

3.1 关键字volatile与死循环

测试案例: 我想通过改变flag的值,从而停止对service的test()方法,进行停止。<span style="font-size:18px;">package org.jksoft.thread.Volatile;
public class Test1 {
public static void main(String[] args) {
Service service = new Service();
service.test();
System.out.println("我要停止他。。。。");
service.setFlag(false);
}
}
class Service{
private boolean flag = true;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public void test(){
while(flag){
System.out.println("run test threadName="+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}</span>  测试结果




结果分析:

     由于test()方法尚未执行完成,所以主线程(main)不会执行后续代码。如果想要解决,当然是用多线程技术了。

3.2  解决同步死循环

   
代码清单:
package org.jksoft.thread.Volatile;

public class Test2 {
public static void main(String[] args) {
final Service2 s2 = new Service2();
Thread thread = new Thread(new Runnable() {
public void run() {
s2.test();
}
},"service2");
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("我要停止他。。。。");
s2.setFlag(false);
}
}
class Service2{
private volatile boolean flag = true;

public boolean isFlag() {
return flag;
}

public void setFlag(boolean flag) {
this.flag = flag;
}
public void test(){
while(flag){
System.out.println("run test threadName="+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}        测试结果:
      




注意:如果没有添加volatile,那么同样的程序运行在JVM为-server服务器的环境中,会出现死锁。

原因:

     1、-server模式为了线程运行的效率,线程一直在私有堆栈中取得的flag的值为true,而main中设置的flag=false,更新的却是公共堆栈中的flag值。

     2、而volatile的作用就是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。

     3、总而言之,就是由于私有堆栈中的值和公共堆栈的值不同步造成的。

3.3 volatile与synchronized的比较

    使用volatile关键字,增加了实例变量在多个线程之间的可见性,但volatile关键字最致命的缺点是不支持原子性。

   1、关键字volatile是线程同步的轻量级表现,所以volatile的性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法,以及代码块。

   2、多线程访问volatile不会发生阻塞,而synchronized会出现阻塞

   3、volatile能保证数据的可见性,但是不能保证原子性。而synchronized可以保证原子性,也可以间接保证可见性,以为它会将私有内存和公共内存的数据作同步

  4、关键字volatile解决的是变量在多个线程之间的可见性;而synchronized关键字解决的是多个线程之间访问资源的同步性。

小结:线程安全包含原子性和可见性两个方面,java的同步机制都是围绕这两个方面来确保线程安全的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: