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

来源:互联网 发布:linux 串口 select 编辑:程序博客网 时间:2024/04/28 12:27

三、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 blocke.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 blocke.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 blocke.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的同步机制都是围绕这两个方面来确保线程安全的。

0 0
原创粉丝点击