Java Sonarint在更新的4.1版本中对Singleton类使用双重锁定时,给出了volatile对象引用的错误

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

我之前已经实现了一个Singleton类,该类对Singleton实例使用双重锁定机制,但是我们得到了一个Sonarint错误,即在双重锁定代码上不应使用双重检查锁定(squid:S2168)

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;
    }
}