volatile底层实现原理和其应用

volatile时轻量级的synchronized,它在多处理器开发中保证了数据的读的一致性,意思就是当一个线程修改一个共享变量时,另外一个线程能读到这个共享变量的值。如果volatile变量修饰符使用的恰当的话,他的运行成本会大大降低,因为他不会引起上下文的切换和调度,因为他并不会阻塞线程,也因此他不能保证多个线程对数据进行写操作时的安全性(即原子性)。

volatile不能保证原子性:

所谓原子性就是,要么都全部过程都执行成功,要么一个都执行不成功。

例如:i++这个操作分为三步

  1. 从内存中取出i
  2. 对i执行+1操作
  3. 将i放回内存中

当它只执行了前两步后就中断了,因此前两步执行成功,但是最后一步失败,i没有回滚减1,因此他不满足原子性,请看如下实例:

public abstract class Test {
	public static void main(String[] args) {
		 MyThread[] mythreadArray = new MyThread[100];
	        for (int i = 0; i < 100; i++) {
	            mythreadArray[i] = new MyThread();
	        }

	        for (int i = 0; i < 100; i++) {
	            mythreadArray[i].start();
	        }
	}
}
class MyThread extends Thread {
    public volatile static int count;

    private static void addCount() {
        for (int i = 0; i < 100; i++) {
            count++;
        }
        System.out.println("count=" + count);
    }

    @Override
    public void run() {
        addCount();
    }
}

结果:

 

按理来说,他应该最后的输出结果时100*100的,这里说明了volatile并不能保证原子性。

那么volatile是怎么实现的呢?

先来看一下volitile的定义是什么,在JAVA语言规范第三版中对volatile的定义如下:Java编程语言允许多线程访问共享变量,为了确保共享变量能被准却和一致地更新 ,线程应该确保通过排他锁单独的获取这个变量。

他通过两步实现其功能:

1、线程通过调用cpu修改值之后,会将缓存行中的数据写回到内存中去。在执行写回操作时,处理器可以独占任何共享空间,而且最近的处理器,lock#信号不会锁总线,而是锁缓存,锁住总线的话,占用的资源太大。

2、写回操作会使在其他cpu里缓存了该内存地址的数据无效。例如在Pentium和P6 faminly处理器中,如果通过嗅探一个处理器来检测其他处理器打算写的内存地址,而这个地址处于共享状态,那么正在嗅探的处理器将会使其自身的缓存行无效,下次访问相同的内存地址时,强制执行缓存行填充。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值