Question

Je suis à la recherche à un certain code de notre application qui, je pense, peut-être la rencontre d'un cas de "Double-vérifier le verrouillage".J'ai écrit un exemple de code qui est similaire à ce que nous faisons.

Quelqu'un peut-il voir comment cela peut être confronté à un double contrôle de verrouillage?Ou est-ce sans danger?

class Foo {
    private Helper helper = null;
    public Helper getHelper() {
        Helper result;
        synchronized(this) {
            result = helper;
        }

        if (helper == null) {
            synchronized(this) {
                if (helper == null) {
                    helper = new Helper();
                }
            }
        }
        return helper;
    }
}

Le code de Base empruntés wiki.

Était-ce utile?

La solution

L'intérêt du verrouillage revérifié est que le chemin rapide (lorsque vous n'avez pas besoin d'instancier l'objet) n'est pas synchronisé.Donc, ce que vous avez n'est pas un verrouillage revérifié.

Vous devez vous débarrasser du premier bloc synchronisé pour obtenir un verrou double-vérifié cassé.Ensuite, vous devez rendre le helper volatil pour le corriger.

Autres conseils

C'est inutilement complexe, la plus sûre façon de faire de la DCL est comme suit:

class Foo {
  private volatile Helper helper = null;
  private final Object mutex = new Object(); 
  public Helper getHelper() {
    if (helper == null) {
        synchronized(mutex) {
            if (helper == null) {
                helper = new Helper();
            }
        }
    }
    return helper;
  }
}

Les points majeurs:

  • Dans les "heureux" cas, nous nous attendons de l'aide pour déjà être attribuée, donc si il est il nous suffit de le retourner sans avoir à entrer un bloc synchronisé.
  • Helper est marqué comme volatile pour permettre au compilateur de savoir que helper peut être lu / écrit par un fil à tout moment et il est important que les lectures / écritures ne sont pas re-commandé.
  • Le bloc synchronisé utilise une variable finale pour synchroniser afin d'éviter un hit potentiel de performance dans le cas d'une autre zone de code de synchronisation sur le this exemple.

Cette partie est un verrouillage double vérifié standard:

if (helper == null) {
    synchronized(this) {
        if (helper == null) {
            helper = new Helper();
        }
    }
}

La première partie est une affectation inutile qui ne fait rien à la partie de verrouillage à double vérification: si l'assistant est null, il est exécuté de toute façon, si ce n'est pas ce ne serait pas exécuté de toute façon.C'est complètement inefficace.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top