Двойное сопоставление с HashMap
Мы работали над куском кода для получения синглтонов. Мы пытаемся получить их, если класс существует в нашей коллекции, мы возвращаем его, в противном случае мы создаем его и сохраняем в нашей коллекции. Мы используем двойную проверку блокировки, чтобы убедиться, что мы не синхронизируемся при каждой операции get.
Однако в соответствии со многими статьями двойная проверка блокировки сломана. Однако я не знаю, так ли это на самом деле, так как карта уже инициализирована и проверка выполняется на ее содержимом. Что, вы парни, думаете? в любом случае, чтобы здесь работал двойной контроль блокировки?
Map <Class <?>, Object> clazzes = getClazzes ();
T singleton = null;
if (false == clazzes.containsKey (clazz))
{
synchronized (clazzes)
{
if (false == clazzes.containsKey (clazz))
{
try
{
singleton = clazz.newInstance ();
clazzes.put (clazz, singleton);
}
catch (InstantiationException e)
{
throw new IllegalArgumentException ( "cannot instantiate class " + clazz, e);
}
catch (IllegalAccessException e)
{
throw new IllegalArgumentException ("cannot instantiate class " + clazz, e);
}
}
else
{
singleton = clazz.cast (clazzes.get (clazz));
}
}
}
Спасибо
2 ответа
Итак, я провел небольшое исследование. Согласно этому документу операция put имеет отношение "происходит до" с ключами. Следовательно, если мы используем ConcurrentHashMap, двойная проверка блокировки должна работать
Не мешать горшок без необходимости, но есть хорошие реализации этого шаблона - что-то вроде https://code.google.com/p/guava-libraries/wiki/CachesExplained
// Construction/setup
LoadingCache<Class<?>, Object> singletons = CacheBuilder.newBuilder()
.build(
new CacheLoader<Class<?>, Object>() {
public Object load(Class<?> key) throws AnyException {
return key.newInstance();
}
});
// client threads
return singletons.get(String.class);
Большим преимуществом этого класса по сравнению с вашей реализацией является то, что вызывающие абоненты блокируют ключ, а не карту. Таким образом, два потока, получающие два отдельных синглета, могут продолжаться. Два потока, получающие один и тот же синглтон, будут ждать его создания.