java - map 的线程安全性,在应用程序范围的 bean 中私下使用,并且仅在构建后用于准备目的

标签 java multithreading jsf concurrency thread-safety

我有一个适用于所有用户的 @ApplicationScoped bean,它在 Trovejava.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/

相关文章:

java - 如何在 Java 中初始化 ThreadLocal 对象

c - 在 C 中在 main 外部定义一个数组,并在 main 内部分配其大小

authentication - JSF 2.3 基于表单的登录和 ViewExpiredException

jsf - 素面 p :dialog keeps reopening

使用 Lambda 表达式进行 Java 排序

java - Android 动画列表 - 简单示例抛出 java.lang.OutOfMemoryError

java - android 创建 .txt 和 .csv 文件抛出 ENOENT No such file or directory 异常

c++ - 同步 QThreads 时出现问题

Java 股票程序随机多线程

jsf - 如何将 <h1>、<h2> 标签放入 <p :fieldset>? 的图例中