Java Sonarint在更新的4.1版本中对Singleton类使用双重锁定时,给出了volatile对象引用的错误
我之前已经实现了一个Singleton类,该类对Singleton实例使用双重锁定机制,但是我们得到了一个Sonarint错误,即在双重锁定代码上不应使用双重检查锁定(squid:S2168)Java Sonarint在更新的4.1版本中对Singleton类使用双重锁定时,给出了volatile对象引用的错误,java,sonarqube,sonarlint,Java,Sonarqube,Sonarlint,我之前已经实现了一个Singleton类,该类对Singleton实例使用双重锁定机制,但是我们得到了一个Sonarint错误,即在双重锁定代码上不应使用双重检查锁定(squid:S2168) public class Singleton { private static Singleton singleton; private Singleton() { } public static Singleton getInstance() { if (singleton == null
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
为了解决这个问题,我考虑将volatile
关键字放在Singleton对象引用之前,如下所示
private static volatile Singleton singleton;
但在将此字段设置为volatile sonalint发出错误后,非原语字段不应为“volatile”(squid:S3077)
这是否意味着现在将对象引用设置为易失性并不是一个好的做法,因为大多数可用的单例示例都与前面提到的代码示例类似?关于您的尝试,Sonar确实给出了
易失性
字段,但根据最新版本,当您使用它时,它看起来似乎自相矛盾。。。。
不明显:)
但是我们得到了一个双重检查锁定的声纳误差不应该是
在双重锁定代码上使用(squid:S2168)
我将删除非常容易出错且冗长的双重检查锁定。即时初始化是线程安全的,在大多数情况下都很好:
public class Singleton {
private static final Singleton singleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return singleton;
}
}
holder类的懒惰方式也是一种选择(我通常会避免,因为懒惰通常不是一种要求):
我们如何知道“即时初始化是线程安全的”?它只是用于
静态关键字吗?是的!静态初始化在类的任何实例化之前完成一次。
public class Singleton {
private static class SingletonHolder{
static final Singleton singleton = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.singleton;
}
}