嗨,大家好!我是你们熟悉的 31 岁程序员大哥哥小米~
最近正在换工作,正好面试了自己超喜欢的一家十八线互联网公司!
不过说真的,这次社招面试我可是吃了不少亏,尤其是碰到并发相关的题目,简直脑瓜嗡嗡的。面试官突然问我:“你知道什么是原子操作吗?Java Concurrency API 里面有哪些Atomic 类?”
???
当时我表面笑嘻嘻,心里 MMP……
回来赶紧复盘查资料,深扒源码,一顿操作猛如虎,今天就把这段血泪教训和大家好好分享一下!如果你也准备社招或者打算换岗,记得收藏好这篇,面试高频考点必备!
什么是原子操作?咱先来搞清楚原子操作到底是个啥玩意。
原子操作(Atomic Operation),简单来说就是不可再分割的最小操作单元,要么不做,要么做完,中间不可能被打断。
在并发编程里,多个线程可能同时操作同一个变量,假如一个操作不是原子的,线程切换到一半就可能会发生数据不一致的问题。
比如:
你以为这是个简单的 +1 ?其实它是三个步骤:
读取变量 i 的值
将值加 1
写回变量 i
如果多个线程同时执行这个操作,就可能发生线程安全问题。
而原子操作的好处是,无论有多少线程,只要这个操作是原子的,就不会出现乱套的情况。线程 A 做这个事,线程 B 只能等着,或者直接做完互不影响。
Java 怎么实现原子操作?
Java 里的原子性是怎么保证的呢?
我们来看看常见的方式:
1. synchronized(重量级)
咱们最熟悉的 synchronized 关键字,它能保证某个代码块同一时刻只允许一个线程进入,等于是给方法/代码块加了个锁。
不过用多了性能不太行,容易阻塞。
2. Lock(更灵活)
java.util.concurrent.locks 包下的 ReentrantLock,比 synchronized 更灵活,可以手动释放锁,支持可中断、公平锁等高级玩法。
3. 原子类 AtomicXXX(轻量高效!)
这才是我们今天的主角。
基于 CAS(Compare And Swap) 和 volatile 实现,性能比加锁方案要好,适合多线程频繁并发的情况。
Java Concurrency API 中的原子类有哪些?好,重头戏来了,Java Concurrency API 给我们提供了一堆好用的Atomic 类,我给你整理了个小米专属清单。
常见 Atomic 类汇总
是不是很多!先别慌,小米给你详细说说用法。
核心 Atomic 类实战详解1、AtomicInteger
核心方法:
get():获取当前值
set(int newValue):设置新值
getAndIncrement():先返回当前值,再自增
incrementAndGet():先自增,再返回值
compareAndSet(int expect, int update):如果当前值等于 expect,才更新为 update,CAS 精髓!
实例演示:
超级简单是不是?
注意这个 compareAndSet,很多原子操作的底层都是靠它搞定的。
2、AtomicReference
作用:原子更新对象引用
比如
这个在多线程下操作对象很有用!
3、AtomicStampedReference
作用:解决 ABA 问题(值变了又变回去,看不出来)
ABA 举个例子:
A:初始值 100,线程1改成 101,线程2又改回 100
B:线程3以为值没变,其实变过
为了避免这种情况,AtomicStampedReference 给对象加个版本号
超稳!
4、LongAdder
作用:高性能计数器,分段锁,减少竞争
适合高并发场景,比 AtomicInteger 性能更好。
建议面试的时候提一下它,面试官会觉得你懂行!
Atomic 原理:CAS + volatile其实这些 Atomic 类的原理主要靠两个招式:
1、CAS(Compare And Swap)
三个值:内存值 V、旧预期值 A、要更新的新值 B
如果 V == A,说明没人动,更新成 B,成功
如果 V ≠ A,说明被改了,失败,继续重试
JVM 提供的 unsafe.compareAndSwapInt() 方法就是这么干的。
2、volatile
所有 Atomic 变量内部的值都是 volatile 修饰,保证了可见性,线程改了,其他线程立马能看到最新值。
面试技巧总结说了这么多,来个小米专属面试答题模板:
原子操作是指在多线程环境下,不可被中断的、完整的操作单元,确保数据一致性。
在 Java Concurrency API 中,主要通过Atomic 类提供原子性保障,如 AtomicInteger、AtomicLong、AtomicReference、AtomicStampedReference、LongAdder 等。
它们基于 CAS(Compare And Swap) 和 volatile 实现,避免了传统加锁的性能开销,适用于高并发环境。
记住,面试的时候别一上来就背,带点场景说明,效果更好:
“在高并发计数的场景里,我更推荐用 LongAdder,因为它分段锁降低了竞争,相比 AtomicInteger 性能更好。”
面试官 :“嗯?小伙子你很懂嘛!”
END今天这篇,算是我跳槽面试踩坑+自我拯救的实录了。
原子操作和 Atomic 类真的很重要,尤其是多线程并发相关的题目,社招、晋升、跳槽基本都少不了。
希望我这篇轻松带故事、带场景、带代码的分享,能帮你在面试里多拿几分!
如果你觉得有用,记得点赞 + 转发 + 收藏啊喂!
小米我会继续分享更多面试经验、源码解析和实战案例,咱们一起卷(不是)成长!
我们下期见!