
1. 并发编程面试的核心考察点在技术面试中并发编程问题往往是最能区分候选人真实水平的试金石。面试官通过这类问题不仅考察你对基础概念的理解更关注你能否将理论知识与实际场景结合。根据我参与过的数百场技术面试经验面试官通常会从以下几个维度评估候选人的并发编程能力基础概念掌握度能否准确解释synchronized、volatile等关键字的底层原理实战问题诊断面对死锁、竞态条件等常见并发问题时的问题定位能力工具选型决策在不同业务场景下选择最合适的并发控制机制性能优化意识对锁粒度、并发度等影响性能的关键因素的把控设计模式应用对读写锁、线程池等并发设计模式的理解深度提示面试中最危险的回答是我在项目里直接用了synchronized没出过问题。这会让面试官认为你缺乏对并发问题的系统性思考。2. synchronized的应答策略与实战陷阱2.1 从JVM层面理解synchronized当被问到synchronized的实现原理时多数候选人只能回答它是重量级锁。更完整的回答应该包含以下层次对象头结构在HotSpot JVM中每个对象头包含Mark Word存储哈希码、GC年龄和锁标志位和Klass Pointer锁升级过程无锁状态初始创建的对象偏向锁通过CAS设置线程ID适用于单线程重复访问场景轻量级锁通过自旋尝试获取锁适合短时间锁竞争重量级锁最终会升级为操作系统层面的互斥量锁消除优化JIT编译器对不可能存在共享数据竞争的锁进行消除锁粗化对连续加锁/解锁操作合并为单个锁操作// 典型错误示例 - 锁对象选择不当 public class WrongLockExample { private String lock lock; // 字符串常量池可能引发意外锁竞争 public void doSomething() { synchronized(lock) { // 业务逻辑 } } }2.2 高频陷阱问题破解问题为什么synchronized不能解决指令重排序问题应答要点明确synchronized的happens-before语义仅保证临界区内操作的可见性指出指令重排序发生在编译期和运行期两个阶段举例说明即使使用synchronized双重检查锁定(DCL)仍可能失效的原因对象初始化操作的指令重排序部分构造的对象被其他线程访问解决方案对比使用volatile修饰实例变量JDK5改用静态内部类实现Holder模式// 正确的DCL实现 public class Singleton { private volatile static Singleton instance; public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } }3. volatile的适用场景与常见误解3.1 内存语义深度解析volatile关键字常被误解为轻量级锁实际上它的核心作用体现在可见性保证写操作会立即刷新到主内存读操作会从主内存读取最新值禁止指令重排序通过内存屏障(Memory Barrier)实现写操作前插入StoreStore屏障写操作后插入StoreLoad屏障读操作前插入LoadLoad屏障读操作后插入LoadStore屏障典型应用场景状态标志位如shutdown请求一次性安全发布如DCL模式独立观察如定期更新的统计值3.2 面试高频问题破解问题volatile能保证原子性吗为什么应答策略明确原子性定义操作不可中断要么全部执行成功要么全部不执行举例说明i这类复合操作的非原子性读取i的值计算i1写入新值对比方案使用AtomicInteger等原子类使用synchronized同步代码块延伸讨论哪些操作在Java中本身就是原子的如long/double在32位JVM上的非原子性问题volatile对32位JVM上long/double读写的原子性保证// 错误用法示例 class Counter { private volatile int count 0; public void increment() { count; // 非原子操作 } } // 正确解决方案1 class AtomicCounter { private AtomicInteger count new AtomicInteger(0); public void increment() { count.incrementAndGet(); } } // 正确解决方案2 class SyncCounter { private int count 0; public synchronized void increment() { count; } }4. Lock接口体系与AQS实现原理4.1 显式锁的优势与选型相比synchronizedLock接口提供了更灵活的并发控制能力特性synchronizedReentrantLock获取超时不支持tryLock(timeout)可中断获取不支持lockInterruptibly()公平锁非公平可配置公平/非公平条件变量单一wait/notify支持多个Condition性能JDK6后优化较好高竞争下表现更好选型建议简单场景优先用synchronized代码更简洁需要高级功能时用ReentrantLock读写比例高时用ReentrantReadWriteLock需要分布式锁时考虑Redisson等方案4.2 AQS实现原理剖析AbstractQueuedSynchronizerAQS是并发包的核心基础组件理解其原理需要掌握核心数据结构state共享资源状态如锁的重入次数CLH队列线程等待队列变种的CLH锁模板方法设计tryAcquire/tryRelease独占模式获取/释放tryAcquireShared/tryReleaseShared共享模式获取/释放典型实现分析ReentrantLock通过state记录重入次数CountDownLatchstate初始化为计数数Semaphorestate表示可用许可数// 自定义基于AQS的简单锁实现 class MyLock extends AbstractQueuedSynchronizer { Override protected boolean tryAcquire(int arg) { return compareAndSetState(0, 1); } Override protected boolean tryRelease(int arg) { setState(0); return true; } public void lock() { acquire(1); } public void unlock() { release(1); } }5. 并发编程综合问题应答框架5.1 死锁问题诊断四步法当面试官给出一个死锁场景时建议采用以下分析框架资源图绘制画出线程与锁的持有/等待关系必要条件验证互斥条件占有且等待非抢占条件循环等待条件解决方案对比锁排序解决循环等待超时机制tryLock死锁检测与恢复预防措施避免嵌套锁使用更高级的并发工具如并发集合5.2 性能优化实战技巧锁粒度控制拆大锁为小锁如ConcurrentHashMap的分段锁热点分离如读写分离无锁化设计使用原子类AtomicInteger等CAS自旋优化ThreadLocal避免共享并发容器选择读多写少CopyOnWriteArrayList高并发写入ConcurrentHashMap延迟队列DelayQueue// 锁粒度优化示例 class OptimizedInventory { private final MapString, Integer items new HashMap(); private final Object[] locks; public OptimizedInventory(int lockCount) { locks new Object[lockCount]; for (int i 0; i lockCount; i) { locks[i] new Object(); } } private Object getLock(String itemId) { return locks[Math.abs(itemId.hashCode()) % locks.length]; } public void updateStock(String itemId, int quantity) { synchronized (getLock(itemId)) { items.merge(itemId, quantity, Integer::sum); } } }在实际面试中遇到并发问题时建议先明确问题边界然后从Java内存模型JMM的基本规则出发逐步展开分析。记住面试官更看重你的思考过程而非完美答案适当地展示你的知识深度和系统性思维往往比快速给出标准答案更有价值。