是否应该同步延迟加载和缓存HashMap中的Object的方法?

Rya*_*n J 3 java multithreading

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Tom*_*icz 5

是的,你是绝对正确的,这种方法需要同步.技术上上下文切换可以在代码中的任何两行之间发生,甚至内部(例如读出和存储之间i++i).

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

即使使用ConcurrentHashMap也无济于事,因为安全putIfAbsent()方法需要给定密钥的现有值 - 而且您可能不希望每次都急切地创建服务.

然而,对于这个相当常见的问题,有一些更好的方法,例如,请参阅:如何实现自填充EHcache?