This method contains an unsynchronized lazy initialization of a non-volatile static field. Because the compiler or processor may reorder instructions, threads are not guaranteed to see a completely initialized object, if the method can be called by multiple threads. You can make the field volatile to correct the problem. For more information, see the Java Memory Model web site.
此方法包含非易失性静态字段的非同步延迟初始化。因为编译器或处理器可能会对指令进行重新排序,所以如果可以由多个线程调用该方法,则不能保证线程能够看到完全初始化的对象。您可以使字段不稳定以更正问题。有关更多信息,请参阅Java内存模型网站。
参考: https://blog.csdn.net/wylsde_zjy/article/details/84881596
错误代码:
// 单线程版本[没有问题] class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null)
helper = new Helper();
return helper;
} // other functions and members...
}
// 多线程版本 --很多东西可能会出错
class Foo2 {
private Helper helper = null;
public synchronized Helper getHelper() {
if (helper == null)
helper = new Helper();
return helper;
} // other functions and members...
}
// 多线程版本--双重检查锁定习惯用法,在优化编译器或共享内存多处理器的存在下不起作用。
class Foo3 {
private Helper helper = null;
public Helper getHelper() {
if (helper == null) // findbugs报错
synchronized (this) {// 同步
if (helper == null)
helper = new Helper();
}
return helper;
} // other functions and members...
}
改正:
// 使用volatile
class Foo5 {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized (this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
}
----------------------------------------------------
引起问题的代码:
public static void register(String dataSourceToolType, DataSourceBuilder builder) {
if (map == null) map = new ConcurrentHashMap<>();
map.put(dataSourceToolType.toLowerCase(), builder);
}
改正后的代码:
private static volatile Map<String, DataSourceBuilder> map = null;
private static byte[] lock=new byte[0];
private DataSourceBuilderFactory() {}
public static void register(String dataSourceToolType, DataSourceBuilder builder) {
if (map == null) {
synchronized (lock) {
map = new ConcurrentHashMap<>();
}
}
map.put(dataSourceToolType.toLowerCase(), builder);
}
源码地址: