在我的应用程序中,我需要维护一个内存中的HashMap
,它存储userIds
列表及其分数
。
有一个 Writer Thread 根据业务逻辑更新用户的分数。并且许多Reader Threads从该 map 中读取用户的score
,即map.get(userId)
。
userIds
列表是静态的,即没有新用户添加到 map 中。
根据 JavaDoc 如果多个线程同时访问 HashMap ,并且至少有一个线程在结构上修改映射,则必须在外部进行同步。
我没有进行任何结构性更改(没有添加/删除)。对于这样的用例,我是否需要使用 ConcurrentHashMap 或任何其他同步构造?
最佳答案
您的map.put
操作只会更新HashMap$Node
的value
字段。就 HashMap
的结构一致性而言,这是安全的,但 value
字段上仍然存在数据竞争。如果您的值类型是一个简单的值类,例如 Integer
、Long
或 Double
,则即使在数据争用中也可以安全地取消引用它,但不能保证消费者会看到更新的分数。
对此的一个干净的解决方案是替换您的例如Long
以 AtomicLong
作为值类型。那么你的 map 将永远不会更新,只有它的值会以线程安全的方式发生变化。
这是解决方案的概要:
安全发布 map :
volatile Map<Player, AtomicLong> scores; void publishScores() { scores = unmodifiableMap(createScoresMap()); }
更新分数:
void updateScore(Player p, long score) { map.get(p).set(score); }
读取乐谱:
long getScore(Player p) { return map.get(p).get(); }
关于java - 如果只有一个writer线程并且没有对map进行结构修改,我们是否需要同步java HashMap gets,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40766688/