面试之volatile关键字

    java面试过程总会遇到不同的面试问题,今天我们就来聊聊volatile关键字, 因为这个关键字可以Java并发编程,java内存模型的一些特征都一个个牵扯进来, 更有甚者可以考察JVM的底层实现以及操作系统的相关知识, 所以面试官往往对volatile乐此不疲:

  问题1: 说说你对volatile关键字的理解?

    被volatile关键字修饰的变量具有以下两个特点:

       1. 保证了不同线程对该变量操作的内存可见性;

       2. 禁止指令重排序.

问题2: 请详细介绍下什么是内存可见性? 什么又是指令重排序?

       这个还得从java内存模型说起, java虚拟机规范试图定义一种java内存模型(JMM), 来屏蔽掉各种硬件与操作系统的内存访问差异, 让java在各种平台上都能达到一致的内存访问效果. 简单来说, 由于CPU执行指令的速度很, 但是内存访问的速度就了许多,相差的不是一个量级,所以搞处理器的设计者们又在CPU里加了好几层高速缓存. 在java内存模型中,对上述的优化又进行了一波抽象. JMM规定所有变量都是存在于主存中的,类似于普通内存,每个线程又包含自己的工作内存,可以理解成CPU上的寄存器或者高速缓存.所以线程的操作主要以工作内存为主, 他们只能访问自己的工作内存, 且工作前后都要把值在同步回主内存中.这样说有点乱,用下边一张图展示一下:

在线程执行时, 首先会从主存中read变量值, 在load到工作内存的副本中, 然后在传给处理器执行,执行完成后再给工作内存中的副本赋值, 随后工作内存中再把值回传给主存,主存中的值更新.JMM就是围绕着在并发过程中如何处理原子性,可见性和有序性这3个特征来建立的,通过解决这3个问题可以解除缓存不一致的问题. 而volatile跟可见性与有序性有关:

问题3: 具体说说这三个特性??

    1) 原子性(Atomicity): java中, 对基本数据类型的读取和赋值操作是原子性操作,所以原子性操作就是指这些操作是不可中断的, 要做就一定做完,要么就没有执行,比如:

    i = 2;
    j = i;
    i++;
    i = i + 1;

上面4个操作中,i=2是读取操作,必定是原子性操作,j=i你以为是原子性操作,其实吧,分为两步,一是读取i的值,然后再赋值给j,这就是2步操作了,称不上原子操作,i++i = i + 1其实是等效的,读取i的值,加1,再写回主存,那就是3步操作了。所以上面的举例中,最后的值可能出现多种情况,就是因为满足不了原子性。

这么说来,只有简单的读取,赋值是原子操作,还只能是用数字赋值,用变量的话还多了一步读取变量值的操作。有个例外是,虚拟机规范中允许对64位数据类型(long和double),分为2次32位的操作来处理,但是最新JDK还是实现了原子操作的。

JMM只实现了基本的原子性,像上面i++那样的操作,必须借助于synchronizedLock来保证整块代码的原子性了。线程在释放锁之前,必然会把i的值刷回到主存的。

     2) 可见性(Visibility): 说到可见性, java就是利用Volatile提供可见性的, 当一个变量被volatile修饰时,那么对它的修改会立刻刷新到主存中, 当其他线程需要用到该变量时,直接去主存中读取新值即可, 而普通变量不能保证做到这一点.

其实要想保证可见性还能使用synchronized和Lock, 线程在释放锁之前,会把变量刷回到主存中,但是synchronized和Lock的开销太大, 太消耗性能,一般不建议使用.

    3) 有序性(Ordering): JMM是允许编译器和处理器对指令重排序的,但是不管怎么排序,程序的结果都不能改变,例如下面一段代码:

double pi = 3.14;       // A
double r = 1;             //  B
double s= pi * r * r;   //  C

上面的语句,可以按照A->B->C执行,结果为3.14,但是也可以按照B->A->C的顺序执行,因为A、B是两句独立的语句,而C则依赖于A、B,所以A、B可以重排序,但是C却不能排到A、B的前面。JMM保证了重排序不会影响到单线程的执行,但是在多线程中却容易出问题。

问题4: Volatile是如何满足并发编程的三大特性的??

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值