
concurrenthashmap 中多个 key 原子操作的实现
在使用 concurrenthashmap 时,对单个 key 的操作是线程安全的。然而,对于跨越多个 key 的复合操作,concurrenthashmap 无法保证原子性。例如,在先 get 后 put 的过程中,其他线程可能会修改 key 对应的值。
高性能解决方案
为了在 concurrenthashmap 中实现多个 key 的原子写入,可以使用以下高性能解决方案:
- copyonwritearrayset 跟踪已存在的 key
使用一个 copyonwritearrayset 跟踪已存在的 key。在写入 concurrenthashmap 之前,先检查 set 中是否存在需要写入的 key。如果不存在,则先写入 set,然后再写入 concurrenthashmap。
通过这种方式,可以确保以下行为:
- 如果某个 key 已存在,所有 key 均不会写入 concurrenthashmap。
- 如果所有 key 都不存在,则在写入 set 和 concurrenthashmap 的过程中间,其他线程无法修改这些 key。
- 递归重试
如果在检查 set 和写入 concurrenthashmap 之间,其他线程修改了某些 key,则可以递归重试写入操作。这将继续直到所有 key 都成功写入或检测到至少一个 key 已存在。
代码示例
以下代码示例演示了如何使用此解决方案:
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
public class MultipleKeyAtomicWrite {
private static final ConcurrentHashMap map = new ConcurrentHashMap<>();
private static final CopyOnWriteArraySet existingKeys = new CopyOnWriteArraySet<>();
public static void main(String[] args) {
// 获取需要写入的 Key
Set keys = new HashSet<>();
keys.add("key1");
keys.add("key2");
keys.add("key3");
// 尝试原子写入 Key
tryAtomicWrite(keys);
// 打印写入结果
System.out.println(map);
}
private static void tryAtomicWrite(Set keys) {
// 检查 Set 中是否存在需要写入的 Key
for (String key : keys) {
if (existingKeys.contains(key)) {
// 已存在某个 Key,放弃写入所有 Key
return;
}
}
// 所有 Key 都不存在,开始写入
boolean success = true;
for (String key : keys) {
success = map.putIfAbsent(key, "value") == null & success;
}
// 如果写入失败(即存在某个 Key),递归重试
if (!success) {
tryAtomicWrite(keys);
}
// 将写入的 Key 添加到 Set 中
for (String key : keys) {
existingKeys.add(key);
}
}
}










