面试题答案
一键面试关键因素
- 数据结构选择
- 鉴于读写操作频率差异较大,对于读操作频繁的场景,哈希表是一个不错的选择,如
HashMap
。它能提供常数时间的平均查找性能。但在高并发场景下,普通HashMap
不适用,因为它不是线程安全的。ConcurrentHashMap
采用分段锁机制,允许多个线程同时对不同段进行操作,大大提高了并发性能,是高并发场景下键值对存储的良好选择。
- 鉴于读写操作频率差异较大,对于读操作频繁的场景,哈希表是一个不错的选择,如
- 线程安全机制
- 锁机制:传统的
Hashtable
使用单一的锁来保证线程安全,但这会导致所有读写操作都要竞争同一把锁,在高并发下性能较差。ConcurrentHashMap
的分段锁机制(Java 7 及之前)或 CAS 操作结合 synchronized 锁(Java 8 及之后)能有效提升并发性能。在 Java 8 中,ConcurrentHashMap
使用 CAS 操作来更新部分数据,只有在必要时才使用 synchronized 锁,减少锁的竞争。 - 无锁数据结构:考虑使用一些无锁数据结构,如
ConcurrentSkipListMap
。它基于跳表数据结构,提供了可排序的键值对存储,并且具有较高的并发性能。适用于需要对键进行排序的场景,且其在高并发下比基于锁的实现有更好的扩展性。
- 锁机制:传统的
- 性能优化策略
- 减少锁粒度:除了上述
ConcurrentHashMap
的分段锁机制外,还可以进一步细分锁的范围。例如,在某些情况下,可以针对特定的键或者键的范围进行加锁,而不是对整个数据结构加锁。 - 读写分离:如果读操作远远多于写操作,可以考虑使用读写锁(
ReadWriteLock
)。读操作可以同时进行,写操作则独占锁,这样可以在一定程度上提高并发性能。
- 减少锁粒度:除了上述
源码层面实现
以下以模拟实现一个简单的基于分段锁的高并发 Map
为例(类似 ConcurrentHashMap
的基本原理):
import java.util.concurrent.locks.ReentrantLock;
public class HighConcurrencyMap<K, V> {
private static final int DEFAULT_SEGMENTS = 16;
private final Segment<K, V>[] segments;
public HighConcurrencyMap() {
segments = new Segment[DEFAULT_SEGMENTS];
for (int i = 0; i < DEFAULT_SEGMENTS; i++) {
segments[i] = new Segment<>();
}
}
private static class Segment<K, V> {
private final ReentrantLock lock = new ReentrantLock();
private final java.util.HashMap<K, V> map = new java.util.HashMap<>();
public V get(K key) {
return map.get(key);
}
public V put(K key, V value) {
lock.lock();
try {
return map.put(key, value);
} finally {
lock.unlock();
}
}
}
public V get(K key) {
int index = hash(key) & (DEFAULT_SEGMENTS - 1);
return segments[index].get(key);
}
public V put(K key, V value) {
int index = hash(key) & (DEFAULT_SEGMENTS - 1);
return segments[index].put(key, value);
}
private int hash(Object key) {
int h;
return (key == null)? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
}
在上述代码中:
HighConcurrencyMap
由多个Segment
组成,每个Segment
内部包含一个HashMap
用于存储键值对,并使用ReentrantLock
来保证线程安全。get
方法不需要加锁,因为HashMap
的读操作本身是线程安全的(除了在扩容等特殊情况下)。put
方法对每个Segment
加锁,从而减少锁的粒度,提高并发性能。hash
方法用于计算键对应的Segment
索引。