Question

Le nouveau modèle de machine de C ++ 11 permet aux systèmes multi-processeurs de fonctionner de manière fiable, WRT. à la réorganisation des instructions.

Comme Meyers et AlexanSrescu a souligné le "simple" Modèle de verrouillage à double vérification L'implémentation n'est pas sûre dans C ++ 03

Singleton* Singleton::instance() {
  if (pInstance == 0) { // 1st test
    Lock lock;
    if (pInstance == 0) { // 2nd test
      pInstance = new Singleton;
    }
  }
  return pInstance;
}

Ils ont montré dans leur article Que peu importe ce que vous faites en tant que programmeur, dans C ++ 03, le compilateur a trop de liberté: il est autorisé à réorganiser les instructions d'une manière que vous pouvez ne pas Assurez-vous que vous vous retrouvez avec une seule instance de Singleton.

Ma question est maintenant:

  • Les restrictions / définitions du nouveau modèle de machine C ++ 11 limitent-elles désormais la séquence d'instructions, que le code ci-dessus fonctionnerait toujours avec un compilateur C ++ 11?
  • À quoi ressemble une mise en œuvre de C ++ 11 sécurisée de ce modèle singleton, lors de l'utilisation des nouvelles installations de bibliothèque (au lieu de la simulation Lock ici)?
Était-ce utile?

La solution

Si pInstance est un pointeur régulier, le code a une course de données potentielle - les opérations sur les pointeurs (ou tout type intégré, d'ailleurs) ne sont pas garanties d'être atomiques (Modifier: ou bien ordonné)

Si pInstance est un std::atomic<Singleton*> et Lock utilise en interne un std::mutex pour atteindre la synchronisation (par exemple, si Lock est en fait std::lock_guard<std::mutex>), le code doit être sans course de données.

Notez que vous avez besoin tous les deux verrouillage explicite et un atomique pInstance pour obtenir une synchronisation appropriée.

Autres conseils

Étant donné que l'initialisation de la variable statique est désormais garantie d'être threadsafe, le singleton du Meyer devrait être Threadsafe.

Singleton* Singleton::instance() {
  static Singleton _instance;
  return &_instance;
}

Vous devez maintenant résoudre le problème principal: il y a un singleton dans votre code.

ÉDITER: Sur la base de mon commentaire ci-dessous: cette implémentation présente un inconvénient majeur par rapport aux autres. Que se passe-t-il si le compilateur ne prend pas en charge cette fonctionnalité? Le compilateur crachera le code dangereux du fil sans même émettre un avertissement. Les autres solutions avec verrous ne se compileront même pas si le compilateur ne prend pas en charge les nouvelles interfaces. Cela pourrait être une bonne raison de ne pas compter sur cette fonctionnalité, même pour des choses autres que les singletons.

C ++ 11 ne change pas la signification de cette implémentation du verrouillage à double vérification. Si vous souhaitez faire du travail à double repection, vous devez ériger des barrières / clôtures de mémoire appropriées.

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