java - 在 HashMap 中延迟加载和缓存对象的方法是否应该同步?

标签 java multithreading

这个方法应该同步吗?我想我不明白上下文切换是如何(以及何时)发生的,所以我不知道是否有可能有多个线程进入我的方法中的 if block 。

public class ServiceLocator {
    private static final Map<Class, Object> applicationServices =
            new HashMap<Class, Object>();

    /**
     * Locates an application scoped service.  The service is lazy loaded and
     * will be cached permanently.
     *
     * @param type The type of service to locate.
     * @return An application scoped service of the specified type.
     */
    @SuppressWarnings({"unchecked"})
    public synchronized static <T> T getApplicationService(Class<T> type) {
        if(!applicationServices.containsKey(type)) {
            // If this method is NOT synchronized, is it possible for more than
            // one thread to get into this if block?
            T newService = ServiceLoader.create(type);
            applicationServices.put(type, newService);
            return newService;
        }
        return (T) applicationServices.get(type);
    }
}

最佳答案

是的,你完全正确,这个方法需要同步。从技术上讲,上下文切换可以发生在代码中的任意两行之间,甚至在代码内部(例如,在 ++i 中读取和存储 i 之间)。

请注意,使用 synchronized 关键字并不意味着当您的线程处于同步块(synchronized block)中时,线程不会被中断,上下文切换也不会发生。这仅意味着任何其他试图在其他线程中执行相同代码的线程都将阻塞,从而有效地允许拥有锁的线程继续执行。

即使使用 ConcurrentHashMap 也无济于事,因为安全的 putIfAbsent() 方法需要给定键的已有值 - 而您可能不想急切地创建每次服务。

然而,对于这个相当普遍的问题,有一些性能更好的方法,例如参见:How to implement Self Populating EHcache?

关于java - 在 HashMap 中延迟加载和缓存对象的方法是否应该同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7790947/

相关文章:

java - 如何拆分字符串并查看它是否是字符串中的最后一个条目?

java - JPA CriteriaBuilder 连接条件转换为分离条件

java - 仅限 map 的工作 - 订单

javascript - Nashorn 多线程编程

c# - 加载大量前期数据。 。同步或异步。

multithreading - 使用第二个共享 OpenGL 上下文加载线程

java - 使用类别作为特征的线性回归

java - 如何使用 Linux Shell 文件运行 TestNG

具有多线程的 Java NIO SocketChannel.read()

c++ - boost 互斥量和类成员访问