我们一直在研究一段代码来获取singeltons。我们尝试获取它们,如果我们的集合中存在类,则返回它,否则我们创建它并将其存储在我们的集合中。我们使用双重检查锁定来确保我们不会在每次获取操作时同步。
然而根据很多文章双重检查锁定被打破。但是我不知道这是否是这种情况,因为地图已经初始化并且对包含进行了检查。你们有什么感想?无论如何要在这里进行双重检查锁定?
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));
}
}
}
由于
答案 0 :(得分:0)
好的,所以我做了一些研究。根据{{3}},put操作与包含键有一个before-before关系。因此,如果我们使用ConcurrentHashMap,则双重检查锁定应该起作用
答案 1 :(得分:0)
不要不必要地搅拌锅,但这种模式有很好的实现 - 比如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);
这个类的优势在于你的实现是调用者阻塞每个键,而不是每个映射。因此,获得两个单独的单身的两个线程都可以继续。获得相同单例的两个线程将等待它构建。