单写单读高写低读场景下嵌套Map无锁同步最优方案咨询
单写单读场景无锁同步方案
方案核心逻辑
利用Java内存模型的happen-before规则+不可变值特性+无锁并发容器,全程不需要加任何显式锁,完全满足你的性能要求:
- Double是不可变类,赋值操作本身是原子操作
- 单写线程负责所有结构修改和值更新,不存在写入竞争
- 读操作仅调用无锁的get方法,不会影响写入性能
1. 数据结构改造
所有Map统一使用ConcurrentHashMap,其get操作全程无锁,且保证写入结果对读线程可见:
// Session -> Symbol -> ID Map<String, Map<String, Long>> mapping1 = new ConcurrentHashMap<>(); // Symbol -> ID -> Level -> Value Map<String, Map<Long, Map<Integer, Double>>> mapping2 = new ConcurrentHashMap<>();
说明:不需要额外加volatile修饰,ConcurrentHashMap本身的内存屏障已经保证了操作的可见性
2. 方法实现调整
addSession/removeSession 实现
无需修改原有逻辑,内层Map也替换为ConcurrentHashMap即可:
void addSession(String session, String symbol, Long id) { mapping1.computeIfAbsent(session, k -> new ConcurrentHashMap<>()) .put(symbol, id); } void removeSession(String session, String symbol, Long id) { Map<String, Long> symbolMap = mapping1.get(session); if (symbolMap != null) { symbolMap.remove(symbol, id); if (symbolMap.isEmpty()) { mapping1.remove(session); } } }
addValue 实现
同样无需修改原有逻辑,内层Map统一用ConcurrentHashMap:
void addValue(String symbol, Long id, Integer level, Double value) { mapping2.computeIfAbsent(symbol, k -> new ConcurrentHashMap<>()) .computeIfAbsent(id, k -> new ConcurrentHashMap<>()) .put(level, value); }
getValue 实现
补充空值判断避免空指针,逻辑保持不变:
Double getValue(String session, String symbol, Integer level) { Map<String, Long> symbolMap = mapping1.get(session); if (symbolMap == null) return null; Long id = symbolMap.get(symbol); if (id == null) return null; Map<Long, Map<Integer, Double>> idMap = mapping2.get(symbol); if (idMap == null) return null; Map<Integer, Double> levelMap = idMap.get(id); if (levelMap == null) return null; return levelMap.get(level); }
3. 方案优势
- 完全无锁:写入操作因为是单线程执行,不会有任何锁竞争开销;读操作全链路无锁,对写入完全无影响
- 性能足够:即使addValue频次提升到每秒万级也完全可以承载,远高于你当前每秒100次的需求
- 安全可靠:严格符合Java内存模型规范,不会出现可见性问题或并发修改异常
补充:不需要做数据结构扁平化,当前分层结构逻辑清晰,且没有额外性能损耗,完全满足需求。
内容的提问来源于stack exchange,提问作者Ishmael
相关产品推荐
相关产品推荐

