面试官:“volatile 你用过吗?” 我一紧张,说错了!

是一名 Java 开发工程师,工作五年,最近正准备跳槽。作为一个有追求的程序员,怎么能不去大厂试试呢?

这天,他兴冲冲地来到了某互联网大厂的面试现场。面试官是个戴着黑框眼镜的资深架构师,简历翻了几页后,微微一笑,开口问道:

“小米,能不能和我聊聊 Java 的 volatile 关键字?你在实际工作中用过它吗?”

小米心里咯噔一下,volatile 这个东西倒是听过,可是……实践?他脑子里迅速回忆起几年前看的 JMM(Java 内存模型)相关的文章,以及自己踩过的坑,清了清嗓子,开始了他的回答。

volatile 是个啥?

小米微笑着说:“volatile 是 Java 里一个轻量级的同步机制,它的主要作用是保证可见性防止指令重排。”

面试官点点头,示意他继续。

“我最开始接触 volatile 这个关键字,是在处理多线程变量可见性问题的时候。”小米回忆道,“有一次,我写了一个简单的标志位,线程 A 负责更新,线程 B 负责读取,结果发现 B 线程一直拿不到 A 线程的最新值。”

他随手写下了当时的代码:

“这段代码你觉得有什么问题?”小米抬头看向面试官。

可见性问题与 volatile 的解法

“问题就在于 stop 变量没有使用 volatile 修饰!”小米继续说道,“在多线程环境下,线程 B 可能永远看不到线程 A 修改 stop 的值。”

为什么会这样?

因为 Java 内存模型(JMM)中,每个线程都有自己的工作内存(线程本地缓存) ,如果一个变量没有被 volatile 修饰,线程 B 可能一直使用自己缓存的 stop,而不是去主内存获取最新值。

但是加上 volatile 之后,stop 的值修改后会立即刷新到主内存,线程 B 读取时也必须去主内存拿最新的值,保证了变量的可见性

小米快速修改代码,加上 volatile:

有了 volatile,线程 A 修改 stop,线程 B 就能立刻感知到变化,不会死循环了!

面试官点点头,继续问道:“那除了可见性,还有什么用?”

volatile 能防止指令重排

小米沉思了一下,说:“还有一个重要作用,就是防止指令重排。”

他继续解释道:

指令重排是 JVM 和 CPU 为了优化程序执行速度,会动态调整指令执行顺序,但这可能导致多线程环境下的代码乱序执行

举个例子,比如在双重检查锁(DCL)中,volatile 主要用来防止指令重排。

如果不加 volatile,可能出现这样的问题:

  • 线程 A 进入 getInstance() 方法,发现 instance == null,准备创建实例。
  • 关键一步:instance = new Singleton(); 这行代码可以被 CPU 重排序为:
  • 分配内存
  • 赋值给 instance(但此时构造方法还未执行完)
  • 执行构造方法
  • 假设此时线程 B 也调用 getInstance(),它看到 instance != null,直接返回这个还没完全初始化的实例,就会导致空指针异常

加上 volatile,可以防止这个指令重排问题,确保 new Singleton() 的顺序是严格按照分配内存 -> 执行构造方法 -> 赋值的顺序进行。

面试官露出了一丝满意的笑容:“不错,你在实际项目中遇到过这个问题吗?”

【机会跳板→技术大厂,前后端or测试捞人,待遇还可以,感兴趣可以试一试。】

volatile 的实践场景

小米点点头:“有,在我们公司,一个订单系统里用到了 volatile。”

他们有一个订单处理系统,某个变量 orderProcessed 需要在多个线程之间共享,保证一个线程修改了它,其他线程能立刻看到变化。

他写出了当时的代码:

这里 volatile 主要确保多个线程能及时看到 orderProcessed 变量的变化,避免多个线程重复处理同一个订单。

volatile 不能做什么?

“不过 volatile 也有局限性。”小米继续补充道,“它不能保证原子性。”

比如 i++ 这种操作,即使加上 volatile 也不能保证线程安全。

这里 count++ 实际上是三个步骤:

  • 读取 count 的值
  • 计算 count + 1
  • 赋值回 count

在多线程环境下,多个线程可能同时读取同一个 count,导致数据覆盖。解决办法是用 AtomicInteger 或 synchronized。

总结:volatile 用于啥?

小米整理了一下思路,总结道:

适用场景

  • 变量可见性问题
  • 防止指令重排(比如 DCL)
  • 状态标志位

不适用场景

  • 不能保证原子性(i++ 仍然需要 AtomicInteger 或 synchronized)

END

面试官听完,微微一笑:“回答不错,你有实际经验,也能深入理解 volatile 的作用。这轮面试通过了!”

小米松了口气,暗暗给自己比了个大拇指。

希望这篇文章能帮到你,下次面试遇到 volatile,你也能自信作答!

我是小米,一个喜欢分享技术的31岁程序员。

——转载自:软件求生

#牛客在线求职答疑中心#
全部评论
我只会valorant
2 回复 分享
发布于 07-07 11:31 北京
厉害厉害,被金山云面试拷打过,看了这个,茅塞顿开
点赞 回复 分享
发布于 07-15 18:04 江苏

相关推荐

06-24 19:11
门头沟学院 Java
大厂人上班最健康的时候只有入职那天,因为要么是好身体的应届生,要么是已修复完成的社招人。高强度工作环境下,互联网从业者的身体健康一直被打上问号,先不说最严重的猝si,互联网从业者几乎都有一点急/慢性病,小问题被一拖再拖就容易成大问题。当然并不是只有互联网人才易得职业病,金融、医护不比互联网轻松,但本人只经历过互联网公司,就聊聊自己和身边互联网人最容易得的一些病症:1.甲状腺结节(女性常有ru腺结节):部门协调、内外衔接的岗位容易得,日常对接总会遇到一些难以沟通或者水平参差的人,加之普遍的工作压力,这是一个高发病症。解决方法:心态调整,把领导的话当屁、把愚蠢同事当NPC、把难做的活往更多人身上推。2.肥胖+胰岛素抵抗+脂肪肝:这三个病症一般连在一起,主要原因还是因为日常糖分摄入过量以及消耗过少,为了犒赏自己,饭要吃好吃饱、奶茶咖啡一杯接一杯,但有限的休息和运动时间让身体的血糖爆表,长期下来就变成了大肚子、大屁股…解决方法:少吃点少喝点,心情不好不要总拿饮食来解决,可以以适度运动搭配理疗、美容等调节3.抑郁症/焦虑症:非常普遍的病症,没有谁能保证自己没有得过,常见于应届生、社招新人、中层管理,简单来说就是绩优主义及高期望投射、高责任感会让人变得敏感、思虑过多。上级的PUA、初入新环境的不适应、团队的混乱等诸多原因总有一个能让人崩溃的。解决方法:没有太好的解决办法,每个人情况不同,个人经常使用的方法就是:把每天都当作当前工作的最后几天来做。然后会发现根本没什么大不了的4.脱发/爆痘:这两个病症主要原因是激素分泌紊乱,主要也是跟互联网的996、熬夜、压力有关,如果本身在学生时期就是易患体质的,真的得重视下,互联网只会让问题放大。解决方法:尽可能早睡早起,严重者及时就诊遵医嘱进行治疗。5.肾结晶/肾结石:不知道有多少人是不爱喝水星人或是重度饮料爱好者。首先是喝水,很多人没有水杯也不买水,往那一坐就是一天。或者每天不喝饮料就不能过活,果葡糖浆及添加剂让肾脏不堪重负。解决方法:多喝水甚至骗猫一样骗自己喝水,少喝或戒掉饮料尤其是瓶装饮料(包括代糖饮料)6.腰肌劳损/腰间盘突出:主要原因是久坐和坐姿不正确(如跷二郎腿)。大厂按平均早10晚9的工作时间,除去早晚休息2小时和摸鱼1小时接水上厕所1小时,其余8个小时完整工作时间里大部分人是坐在位置上的,日积月累的劳作下来,铁腰也扛不住。解决方法:还没有患病的,买人体工学椅+间歇性站立/站立办公(桌面升降桌),不是广也不是智商税,看下老板们坐的和硅谷顶尖互联网企业的配置就明白了;如果已经出问题了及时治疗并亡羊补牢。7.肠胃炎+幽门螺杆菌:这个其实也算是高发病症,目前许多大厂有食堂或者送餐福利,但由于就餐时间限制和种类较少,再叠加一个工作压力和临时开会因素,许多人不能好好吃饭(包括但不限于不按时吃、不吃、吃太多、吃太快、吃得太单一),你的就餐规律对肠胃来说成了谜,长期下来它们也不知道在什么时候工作合适,就成了肠胃炎。幽门杆菌这个容易聚餐被传染,叠加肠胃炎绝了,不是biubiubiu就是enenen(意会),长期病患容易演变成息肉、溃疡或癌症,有些销售岗需要对外应酬的更要注意适度饮酒。解决办法:按时吃饭或者吃健康的代餐,应酬推不掉就给自己找点清淡的菜品,吃饭时尽量多咀嚼一下别暴风吸入,每顿吃到七分饱,没吃饱可以用少量坚果或者酸奶补充能量8.胆结石:最大的病因就是不吃早饭。有些厂上班都快中午了,每天吃饭都是brunch和dinner,很多人还暗自窃喜公司帮自己完成了16+8轻断食,殊不知不是每个人的体质都能这样,结果胆结石痛到做手术才幡然醒悟。解决方法:早饭能吃的尽量吃一点,早上胃酸过多就吃苏打饼或者碱面馒头,晚上胃酸过多可以喝硫糖铝口服液舒缓。如有严重问题尽快就医。9.睡眠障碍(入睡困难/失眠/多梦):这个上篇没提到但估计90%大厂人都有这个问题,并且是诸多病症的最大诱因。据身边同事说,凌晨1点前入睡的不超过10%、2点前不超过60%,对了一下睡前行为后发现主要就是下班晚+手机刺激+焦虑,但没几个人可以自律到每天早睡,毕竟没有老板没有工作的夜晚太迷人了…解决方法:睡前减少蓝光刺激,精神紧张就去按摩等方式放松,或者适量饮酒完成助眠。10.永久性损伤(脑雾、听力、视力):长时间用脑过度,脑细胞将重建缓慢,神经性损伤很难修复,除非有更大的刺激脑神经,才会修复,目前医术水平还没有能根治的,最多药物辅助治疗。很多年轻时,有伟大成就的科学家,老年也变得老年痴呆,也是因为用脑过度,思考过度。听力,人习惯戴降噪入耳耳机,长时间听,也是永久性损伤。视力也更不用说了,很多人必须长时间盯着各种电子屏幕。解决办法:换个行业公众号:******
投递新环境等公司7个岗位
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-11 11:39
给我开两千工资还好意思,笑死我没,还转正才交社保,别太离谱啊我说
机械打工仔:前几天还看到一个试用期不让交社保的,今天就看到个实习期就要社保的,也算是开了眼了
点赞 评论 收藏
分享
评论
7
17
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务