作家
登录

Java面试官最爱问的volatile关键字

作者: 来源: 2018-01-19 11:44:46 阅读 我要评论

年前最后一场技巧盛宴 | 1月27日与京东、日记易技巧大年夜咖畅聊智能化运维成长趋势!


在Java相干的岗亭面试中,很多面试官都爱好考察面试者对Java并发的懂得程度,而以volatile关键字作为一个小的切入点,往往可以一问到底,把Java内存模型(JMM),Java并发编程的一些特点都牵扯出来,深刻地话还可以考察JVM底层实现以及操作体系的相干常识。 下面我们以一次假想的面试过程,来深刻懂得下volitile关键字吧!

如不雅把参加volatile关键字的代码和未参加volatile关键字的代码都生成汇编代码,会发明参加volatile关键字的代码会多出一个lock前缀指令。 lock前缀指廖实际相当于一个内存樊篱,内存樊篱供给了以下功能:

  1. 重排序时不克不及把后面的指令重排序到内存樊篱之前的地位
  2. 使得本CPU的Cache写入内存 ** **
  3. 写入动作也会引起其余CPU或者其余内核无效化其Cache,相当于让新写入的值对其余线程可见。

假如有两个线程履行上述代码段,线程1先履行write,随后线程2再履行multiply,最后ret的值必定是4吗?结不雅不必定:

4.传递性:如不雅A happens-before B ,且 B happens-before C, 那么 A happens-before C

面试官: Java并发这块懂得的怎么样?说说你对volatile关键字的懂得

就我懂得的而言,被volatile润饰的共享变量,就具有了以下两点特点:

  1. 包管了不合线程对该变量操作的内存可见性;
  2. 禁止指令重排序

面试官: 能不克不及具体说下什么是内存可见性,什么竽暌怪是重排序呢?

这个聊起来可就多了,我照样大年夜Java内存模型说起吧。 Java虚拟机规范试图定义一种Java内存模型(JMM),来樊篱掉落各类硬件和操作体系的内存拜访差别,让Java法度榜样在各类平台上都能达到一致的内存拜访效不雅。简单来说,因为CPU履行指令的速度是很快的,然则内存拜访的速度就慢了很多,相差的不是一个数量级,所以搞处理器的那群大年夜佬们又在CPU里加了好几层高速缓存。

在Java内存模型里,对上述的优化又进行了一波抽象。JMM规定所有变量都是存在主存中的,类似于膳绫擎提到的通俗内存,每个线程又包含本身的工作内存,便利懂得就可以算作CPU上的存放器或者高速缓存。所以线程的操作都是以工作内存为主,它们只能拜访本身的工作内存,且工作前后都要把值袈溱同步回主内存。 这么说得我本身都有些不清跋扈了,拿张纸画一下:

在线程履行时,起首会大年夜主存中read变量值,再load到工作内存中的副本中,然后再传给处理器履行,履行完毕后再给工作内存中的副本赋值,随后工作内存再把值传回给主存,主存中的值才更新。 应用工作内存和主存,固然加快的速度,然则也带来了一些问题。比如看下面一个例子:

  1. i = i + 1; 

假设i初值为0,当只有一个线程履行它时,结不雅肯定获得1,当两个线程履行时,会获得结不雅2吗?这倒不必定了。可能存在这种情况:

  • 线程1: load i from 主存 // i = 0
  • i + 1 // i = 1
  • 线程2: load i from主存 // 因为线程1还没将i的值写回主存,所以i照样0
  • i + 1 //i = 1
  • 线程1: save i to 主存
  • 线程2: save i to 主存

如不雅两个线程按照膳绫擎的履行流程,那么i最后的值居然是1了。如不雅最后的写复生效的慢,你再攫取i的值,都可能是0,这就是缓存不一致问题。 下面就要提到你刚才问到的问题了,JMM重要就是环绕着如安在并发过程中若何处理原子性、可见性和有序性这3个特点来建立的,经由过程解决这三个问题,可以解除缓存不一致的问题。而volatile跟可见性和有序性都有关。

面试官:那你具体说嗣魅这三个特点呢?

1.原子性(Atomicity): Java中,对根本数据类型的攫取和赋值操作是原子性操作,所谓原子性操作就是指这些操作是弗成中断的,要做必定做完,要么就没有履行。 比如:

膳绫擎4个操作中,i=2是攫取操作,必定是原子性操作,j=i你认为是原子性操作,其实吧,分为两步,一是攫取i的值,然后再赋值给j,这就是2步操作了,称不上原子操作,i++和i = i + 1其实是等效的,攫取i的值,加1,再写回主存,那就是3步操作了。所以膳绫擎的举例中,最后的值可能出现多种情况,就是因为知足不了原子性。 这么说来,只有简单的攫取,赋值是原子操作,还只能是用数字赋值,用变量的话还多了一步攫取变量值的操作。有个例外是,虚拟机规范中许可对64位数据类型(long和double),分为2次32为的操作来处理,然则最新JDK实现照样实现了原子操作的。 JMM只实现了根本的原子性,像膳绫擎i++那样的操作,必须借助于synchronized和Lock来包管整块代码的原子性了。线程在释放锁之前,必定会把i的值刷回到主存的。 2. 可见性(Visibility): 说到可见性,Java就是应用volatile来供给可见性的。 当一个变量被volatile润饰时,那么对它的修改会急速刷新到主存,当其它线程须要攫取该变量时,会去内存中攫取新值。而通俗变量则不克不及包管这一点。 其实经由过程synchronized和Lock也可以或许包管可见性,线程在释放锁之前,会把共享变量值都刷回主存,然则synchronized和Lock的开销都更大年夜。 3. 有序性(Ordering) JMM是许可编译器和处理器对指令重排序的,然则规定了as-if-serial语义,即不管怎么重排序,法度榜样的履行结不雅不克不及改变。比如下面的法度榜样段:

  1. double
     1/5    1 2 3 4 5 下一页 尾页

      推荐阅读

      剖析内存中的程序之秘,快来看吧!

    年前最后一场技巧盛宴 | 1月27日与京东、日记易技巧大年夜咖畅聊智能化运维成长趋势! ELF Binary Image Mapped Into MemoryKernel/User Memory Split内存治理是操作体系的核心义务;它对法>>>详细阅读


    本文标题:Java面试官最爱问的volatile关键字

    地址:http://www.17bianji.com/lsqh/40382.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)