Android 面试题库:深度解析并发锁机制与应用实践
在 Android 高级开发面试中,并发锁是考察候选人底层功底、内存模型理解以及系统架构能力的核心考点。本文针对 Android 实际开发场景,系统性梳理了各种锁的原理与选型。
一、 Java 基础锁原语
1. synchronized (内置锁/监视器锁)
- 特性:自动获取/释放、可重入、非公平。在现代 ART 虚拟机中经过了偏向锁、轻量级锁、重量级锁的膨胀优化。
- 面试考点:
- 对象锁 vs 类锁:同步代码块与静态同步方法的区别。
- 原理:每个对象关联的
monitor对象(EntryList, WaitSet)。
- 应用场景:本项目的
GLTextureView中用于状态机的全局调度。
2. ReentrantLock (显示锁)
- 特性:基于 AQS(AbstractQueuedSynchronizer)实现。支持公平/非公平选型、可中断、支持超时获取、多条件变量(Condition)。
- 面试考点:
- 与
synchronized区别:灵活性(tryLock)、性能(高竞争下更稳定)、可扩展性。
- 与
- 应用场景:复杂的数据结构操作,或需要响应中断的长时间等待场景。
二、 读写与性能优化锁
3. ReentrantReadWriteLock (读写锁)
- 核心逻辑:读读共享、读写互斥、写写互斥。
- 面试考点:
- 锁降级:写锁可以降级为读锁,但读锁不能升级为写锁。
- 饥饿问题:大量读操作可能导致写操作长时间无法获取锁。
- 应用场景:App 的内存缓存(LruCache)查询频率远高于更新频率的场景。
4. StampedLock (乐观读锁)
- 特性:Java 8 引入。提供了一种乐观读模式,读操作不会阻塞写操作。
- 面试考点:
- 对比 ReadWriteLock:通过版本戳(Stamp)验证数据有效性,在读多写极少的极端场景下性能近乎无锁。
- 应用场景:坐标点数据计算、频繁读取的配置信息。
三、 原子操作与轻量级同步
5. CAS (Compare And Swap)
- 原理:利用 CPU 的
cmpxchg指令实现无锁原子更新。 - 面试考点:
- ABA 问题:如何通过
AtomicStampedReference解决。 - 自旋开销:高竞争下 CPU 占用率过高。
- ABA 问题:如何通过
- 应用场景:计数器(AtomicInteger)、状态标记位。
6. volatile 关键字
- 作用:可见性、有序性(禁止指令重排)。不保证原子性。
- 面试考点:
- DCL(双重检查锁定)单例模式:为什么必须加
volatile?(防止对象初始化未完成就被引用)。
- DCL(双重检查锁定)单例模式:为什么必须加
- 应用场景:本项目的
mHasContentToDraw标志位同步。
四、 Android 场景下的特有应用
7. 渲染链路同步 (本项目核心)
- 痛点:GL 线程与 UI 线程的生命周期不同步。
- 方案:使用
synchronized配合wait/notifyAll构建保护性暂停(Guarded Suspension)模型。 - 面试回答:参考
GLTEXTUREVIEW_LOCKING.md中的握手协议描述。
8. 锁的选型指南 (横向对比)
| 维度 | synchronized |
ReentrantLock |
Atomic/CAS |
|---|---|---|---|
| 灵活性 | 低(自动) | 高(手动控制) | 极高(无锁) |
| 性能 | 中(低中竞争优) | 高(高竞争稳定) | 极高(极短操作) |
| 功能 | 基础 | 丰富(Condition/公平性) | 仅限原子变量 |
| 风险 | 低 | 高(易忘释放) | 容易出现 ABA 问题 |
五、 资深面试官进阶追问
Q1:如何定位 App 线上发生的死锁?
- 答:1. 使用
Thread.getAllStackTraces()获取堆栈。2. 寻找BLOCKED状态的线程。3. 分析锁的循环等待链(A 等 B,B 等 A)。
Q2:为什么 ConcurrentLinkedQueue 不需要加锁?
- 答:它采用了 Michael-Scott 非阻塞队列算法,底层完全基于 CAS 操作头尾指针,实现了极高的并发吞吐量。本项目在
HybridNormalRenderer中使用它来处理弹幕队列,避免了每一帧渲染都要持锁的开销。
Q3:什么是偏向锁和锁消除?
- 答:锁消除是 JIT 编译器的优化,若发现对象只会在单线程访问,则直接去掉
synchronized。偏向锁是假设锁一直由同一线程持有,减少 CAS 操作开销。
📌 总结
锁不是越多越好,而是越轻量越好。在 Android 开发中,首选无锁结构(Concurrent 容器),次选轻量级标记(volatile/Atomic),最后才考虑重权重的 Monitor 或显示锁。