面试题答案
一键面试线程安全问题分析
- 数据不一致:多个线程同时对 TreeMap 进行插入、删除或修改操作时,可能导致数据状态不一致。例如,一个线程在读取 TreeMap 时,另一个线程正在进行插入操作,可能读到不完整或错误的数据。
- 排序混乱:由于 TreeMap 是按照自定义排序规则排序的,多线程并发操作可能破坏排序逻辑。例如,不同线程同时插入元素,可能导致元素在内部存储结构(红黑树)中的位置不正确,进而破坏排序的正确性。
解决方案及优缺点
- 使用 Collections.synchronizedSortedMap 包装 TreeMap
- 实现方式:
TreeMap<K, V> treeMap = new TreeMap<>(customComparator);
SortedMap<K, V> synchronizedMap = Collections.synchronizedSortedMap(treeMap);
- **优点**:实现简单,不需要对 TreeMap 的内部逻辑做太多修改。通过同步整个 Map 的操作,保证了线程安全。
- **缺点**:性能较低,因为所有操作都被同步,在高并发环境下,竞争锁会成为性能瓶颈。
2. 使用 ConcurrentSkipListMap - 实现方式:
ConcurrentSkipListMap<K, V> skipListMap = new ConcurrentSkipListMap<>(customComparator);
- **优点**:性能较高,它采用跳表数据结构,支持高并发读写。读操作通常不涉及锁,写操作通过锁分段技术,减少锁竞争。同时能保证排序的正确性。
- **缺点**:内存占用比 TreeMap 大,因为跳表结构需要额外的指针空间。
3. 自定义同步机制 - 实现方式:继承 TreeMap 类,然后在需要同步的方法(如 put、get、remove 等)上添加 synchronized 关键字,或者使用 ReentrantLock 等锁机制手动控制同步。
class SynchronizedTreeMap<K, V> extends TreeMap<K, V> {
private final Object lock = new Object();
@Override
public V put(K key, V value) {
synchronized (lock) {
return super.put(key, value);
}
}
// 类似地同步其他方法
}
- **优点**:可以根据实际需求灵活控制同步粒度,比 Collections.synchronizedSortedMap 更细粒度的控制,性能可能更好。
- **缺点**:实现复杂,需要对 TreeMap 的内部方法和线程同步机制有深入理解,且维护成本较高。