我有一个适用于所有用户的 @ApplicationScoped
bean,它在 Trove
和 java.util
中存储 ids-> 名称,反之亦然 map 。
我只是在构建 bean 时构建一次 map 或(在网站管理员手动刷新的情况下)。
在 bean 方法中,我只是将 get()
与 map 一起使用,所以没有修改 map 。这将是线程安全的,因为它仅用于就绪目的吗?我不会与外部的任何其他 bean 共享 map ,也不会在我的代码中随时修改 map (添加/删除条目)。
此外,在这种情况下是否有必要将字段设置为最终字段?
bean代码如下:
@ApplicationScoped
@ManagedBean(name="directory", eager=true)
public class directory {
private static TIntObjectHashMap<String> idsToNamesMap;
private static TreeMap<String, Integer> namesToIdsMap;
@PostConstruct
public void buildDirectory(){
// building directory here ....
}
public String getName(int topicId){
return idsToNamesMap.get(topicId);
}
public List<Entry<String, Integer>> searchTopicsByName(String query){
return new ArrayList(namesToIdsMap.subMap(query, true, query+"z", true).entrySet());
}
}
最佳答案
在这种情况下,您不必将它们声明为 volatile 或使用任何类型的同步进行保护。只要构建线程就会构建它们并与主存同步。
为此,构造线程只需要对 volatile 变量进行一次写入或进入/退出同步锁。这将通过内存屏障,所有本地线程数据都将在主线程中。然后所有其他线程读取此数据将是安全的。
甚至更多 - 不必要的 volatile 或同步块(synchronized block) - 会导致严重的性能损失 - 每次访问变量时都会通过内存屏障 - 这是一项昂贵的操作
关于java - map 的线程安全性,在应用程序范围的 bean 中私下使用,并且仅在构建后用于准备目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10115399/