Volatile作用

在多线程环境下,对于主内存中的共享变量,每个线程都有自己的一份拷贝值,便于自己线程内的操作,这也会导致一个问题,当有一个线程修改主内存中的变量值时,其他线程内拷贝的变量值还是旧值,没有获取最新的值。因此我们就可以使用volatile关键字修饰变量,它可以保证内存可见性和避免指令重排序。当有线程修改主内存中的变量值时,会导致其他线程中拷贝的变量值失效,当线程内读取自己线程内存中的变量值时会发现变量值已失效,就会从主内存重新读取变量值到自己线程内存中。以此来达到及时获取最新的变量值。但是volatile没有synchronized的同步原语,无法保证原子性。即在变量操作环境下仍然是不安全的。比如,volatile修饰的变量,两个线程a、b已经读取了主内存中的变量值并进行++操作,其中a线程先进行++操作,并更新主内存中的变量值,同时使b线程内的变量缓存值失效,但是如果b线程已经在a线程更新变量值之前就读取过了变量值,b就不会再重新读取主内存的值,即使这时缓存的值已经失效,b线程就会在原来的值基础上进行++操作,导致操作错误。

下面看一下在没有volatile关键字修饰时,修改变量的值不能时循环停止的情况。

/**
 * Volatile保证变量内存可见性
 * @author SN
 *
 */
public class VolatileRead extends Thread{
	private /*volatile*/ boolean flag=true;
	
	public void setValue(boolean flag){
		this.flag=flag;
		System.out.println("设置flag:"+flag);
	}
	
	@Override
	public void run(){
		//run方法内是另启动的线程,其使用的flag值是线程内拷贝的主内存的值
		while (flag) {
			//System.out.println("#########");
		}
		System.out.println("循环结束,flag:"+flag);
	}
	
	public static void main(String[] args) throws InterruptedException {
		VolatileRead vr=new VolatileRead();
		vr.start();
		Thread.currentThread().sleep(3000);
		vr.setValue(false);
		System.out.println("flag:"+vr.flag);
	}
}

执行程序,可以看到程序没有停止,仍然在循环,这是因为虽然在main方法中修改了flag的值,但是由于while循环是在另外启动的线程中运行的,这个线程中读取的flag值是线程内缓存的主内存中的flag值,仍然是true,所以循环没有结束。如果将flagvolatile修饰就可以了。

另外在while循环中加上一句System.out的打印语句也可以使线程停止,因为System.outjdk线程调用的,怀疑是自动刷新了线程内的flag值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值