构造函数是静态的,而且不管是否为private还是public修饰,他都是静态的。
《JAVA并发编程实战》有提过:
“”如果构造方法暴露了this指针,就会存在线程安全问题“”
其意思是,构造方法是静态的,非线程安全的,如果在这个非线程安全的方法中读写对象的成员,比如初始化对象,就会存在线程安全问题。
比如:
class Holder {
private int n;
public Holder( int n){
this.n = n;
}
}
在dubbo的ExtensionLoader也存在这个问题:
@SuppressWarnings("unchecked") public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { if (type == null) throw new IllegalArgumentException("Extension type == null"); if(!type.isInterface()) { throw new IllegalArgumentException("Extension type(" + type + ") is not interface!"); } if(!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!"); } ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; } private ExtensionLoader(Class<?> type) { this.type = type; objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); }
下面的构造方法做了非线程安全的赋值操作
这个extensionLoader的是单例缓存的,在构造的时候没有同步,直接被用来初始化.
所以存在线程安全。
造成的结果:获取扩展类的时候,可能会失败,但这个问题不会影响dubbo的正常时候,只会占用内存