あなたのメソッドはスレッドセーフではありません:
private static Map<Class<MyClass<?>>, MyClass<?>> s_instances =
    new HashMap<Class<MyClass<?>>, MyClass<?>>();
public static MyClass<?> blah(Class<MyClass<?>> clz)
        throws InstantiationException, IllegalAccessException {
    if (s_instances.get(clz) != null)
        return s_instances.get(clz);
    // here1
    MyClass<?> instance = clz.newInstance();
    s_instances.put(clz, instance);
    // here2
    return instance;
}
1つのスレッドがマークされた行を通過すると//here1、最初のスレッドがマークされた行に到達する前に2番目のスレッドがメソッドに入る可能性があります//here2。したがって、同じ種類の2番目の「シングルトン」が作成され、マップの最初のスレッドが上書きされます。
手っ取り早い解決策は、マップ上で同期することです。
public static MyClass<?> blah(Class<MyClass<?>> clz)
        throws InstantiationException, IllegalAccessException {
  synchronized(s_instances){
    if (s_instances.get(clz) != null)
        return s_instances.get(clz);
    // here1
    MyClass<?> instance = clz.newInstance();
    s_instances.put(clz, instance);
    // here2
    return instance;
  }
}
ただし、これは、多くのスレッドが多くの時間を待たなければならず、最終的にはアプリケーションを強制終了することを意味します。おそらくあなたがすべきことは2段階の解決策です:
public static MyClass<?> blah(Class<MyClass<?>> clz)
        throws InstantiationException, IllegalAccessException {
  Object candidate = s_instances.get(clz);
  if(clz.isInstance(candidate)){ // implicit null check
      return clz.cast(candidate);
  }
  synchronized(s_instances){
    Object candidate = s_instances.get(clz);
    if(clz.isInstance(candidate)){  // gotta check a second time in a
        return clz.cast(candidate); // synchronized context
    }
    MyClass<?> instance = clz.newInstance();
    s_instances.put(clz, instance);
    return instance;
  }
}
また、HashMapは同時アクセスには適していないため、次のようにラップする必要がありますCollections.synchronizedMap()。
private static Map<Class<MyClass<?>>, MyClass<?>> s_instances =
    Collections.synchronizedMap(new HashMap<Class<MyClass<?>>, MyClass<?>>());
またはConcurrentHashMap代わりに行きます。