Without synchronized keyword, a thread can call register() or unregister() while another thread is executing this method. Did you consider those cases already?

As you know, this method calls register() and cache.get() at some points. So we need to take account of such as the case that thread#A calls unregister() while thread#B is executing in the middle of lookupInterfaceTypes().