题目重点:解释并发 map 的可见性、复合更新、迭代语义与跨键事务边界。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 以 Java 21 API 为参考;实现版本不同,不统一称为分段锁。
解题路线
- 单个 map 操作线程安全,但 get 后 put 是两个操作。计数使用 merge/compute 或合适的原子值,避免丢更新。
- 常见现代实现结合桶级协调和 CAS 等技术;解释热点桶与扩容协作,不把实现细节当永久规范。
- get 通常不阻塞,迭代弱一致而非冻结快照;size 在并发更新时不适合作为精确控制条件。不允许 null 键和值。
- compute 回调应短小,不在内做网络 I/O 或递归修改相关映射。跨两个键的守恒约束不是自动事务,需要额外协调。
手动走一遍
两个线程都读取0然后各 put1,最终只有1;merge(k,1,Integer::sum) 按该键原子更新能保留两次增量。从 A 扣钱再给 B 加钱即便各自 compute,也会存在中间状态;转账合同需要一体事务。
规模与取舍
良好散列下查找通常平均 O(1),热点键限制并发吞吐。大型 map 的遍历与内存成本仍随规模增长。
易错点与追问
容易失分的边界
- 线程安全容器保证任意多步算法原子。
- size 精确快照。
- 在 compute 里执行慢远程请求。
继续深挖
- LongAdder 适合计数但适合精确限额吗?
- 如何获取一致快照?
技术参考
- ConcurrentHashMap API:技术语义参考,具体题目按本文约定。
