大厂Java后端二面面经:华为字节实习背景冲刺拼多多
《面试题目》
- 自我介绍及简历经历追问(如”为什么在某厂只待了三个月,是否转正”)
- HashMap 与 TreeMap 的区别?
- HashMap 在多线程场景下有什么问题?怎么解决?
- CAS 重试会带来什么问题?怎么解决?
《参考解析》
- HashMap 与 TreeMap 的区别:TreeMap 底层基于红黑树实现,元素有序,查找/插入的时间复杂度为 O(logN);HashMap 底层是数组 + 链表(链表长度超过阈值转红黑树),元素无序,理想情况下查找/插入时间复杂度为 O(1)。需要有序遍历或范围查找时选 TreeMap,追求极致读写性能选 HashMap。
- HashMap 的多线程问题:JDK 1.7 及以前扩容时链表头插法在多线程下可能形成环导致死循环;JDK 1.8 之后虽然改为尾插法规避了成环问题,但并发 put 仍可能导致数据覆盖、size 计数不准等线程安全问题。JDK 1.8 引入了
synchronized + CAS的方式保证扩容和写入的原子性:扩容前先通过 CAS 检查节点是否被其他线程修改,若被修改则重试。 - CAS 重试的问题与解决:CAS 本身不会阻塞线程,但失败后的重试基于自旋实现,高并发下会持续占用 CPU 时间;同时存在 ABA 问题(值被改回原值导致 CAS 误判”未变化”)。解决办法是限定自旋次数或加超时时间,避免无限自旋;ABA 问题可以用
AtomicStampedReference引入版本号(时间戳)来解决,只要版本号变化就能感知到中间被修改过。超过重试次数仍失败时,会退化为使用synchronized加锁保证安全。