java - 并发访问unmodifiableMap

标签 java jakarta-ee concurrency unmodifiable

@Singleton
@LocalBean
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class DeliverersHolderSingleton {

    private volatile Map<String, Deliverer> deliverers;

    @PostConstruct
    private void init() {
        Map<String, Deliverer> deliverersMod = new HashMap<>();
        for (String delivererName : delivererNames) {
            /*gettig deliverer by name*/
            deliverersMod.put(delivererName, deliverer);
        }
        deliverers = Collections.unmodifiableMap(deliverersMod);
    }

    public Deliverer getDeliverer(String delivererName) {
        return deliverers.get(delivererName);
    }

    @Schedule(minute="*", hour="*")
    public void maintenance() {
        init();
    }
}

单例用于存储数据。数据每分钟更新一次。 从 unmodifiableMap 中读取是否有可能是同步问题?是否有可能会在 init 方法中发生重新排序并发布到集合的链接,但集合未完全填充?

最佳答案

Java 内存模型保证 there is a happens-before relationship between a write and a subsequent read to a volatile variable .换句话说,如果你写入一个 volatile 变量并随后读取同一个变量,你可以保证写入操作是可见的,即使涉及多个线程也是如此:

A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.

它更进一步并保证在写入操作之前发生的任何操作在读取点也将是可见的(由于程序顺序规则和 happens-before 关系是可传递的事实).

您的 getDeliverers 方法从 volatile 变量读取,因此它将看到在行 deliverers = Collections.unmodifiableMap(deliverersMod); 以及前面的行上进行的最新写入操作填充 map 的操作。

因此您的代码是线程安全的,并且您的 getDeliverers 方法将根据最新版本的 map 返回结果。

关于java - 并发访问unmodifiableMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17472280/

相关文章:

jakarta-ee - 添加到 ArrayList 时 Tomcat 上的运行时异常

java - N+1 HTTP 调用通过同时队列进行批处理

Java插件开发调试接口(interface)问题

java - 如何在 MyBatis 动态 SQL 的带注释映射器中使用 XML ResultMap?

css - 首次运行时未加载 Spring mvc 资源

java - 设置org.springframework.scheduling.quartz.JobDetailBean的bean属性 'jobClass'

Java 字符串插入排序未按预期工作

java - 如何设置文本下划线?

javascript - jQuery/AJAX并发访问全局变量

java - 什么是最好/最优雅的方式来限制并行流中并发评估的数量(比如使用固定线程池)