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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值