这个方法应该同步吗?我想我不明白上下文切换是如何(以及何时)发生的,所以我不知道是否有可能有多个线程进入我的方法中的 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/