Maison développement back-end Tutoriel C#.Net Implémentation du modèle singleton C# et exemples de comparaison des performances

Implémentation du modèle singleton C# et exemples de comparaison des performances

May 16, 2018 pm 05:08 PM
.net

Cet article présente principalement des informations pertinentes sur l'implémentation et la comparaison des performances du mode singleton C#. Il présente en détail 6 méthodes d'implémentation. Les amis dans le besoin peuvent se référer à l'

Introduction

Un singleton fait référence à une classe qui ne peut avoir qu'une seule instance (en C#, plus précisément, c'est une classe qui ne peut avoir qu'une seule instance dans chaque AppDomain. Elle est utilisée en génie logiciel comme l'un des modes les plus courants. Une fois que le premier utilisateur a créé une instance de cette classe, les utilisateurs suivants qui doivent utiliser cette classe ne peuvent utiliser que l'instance créée précédemment et ne peuvent pas créer une nouvelle instance. Un singleton est créé lors de sa première utilisation. plusieurs méthodes d'implémentation singleton en C# et analysez les différences de sécurité et de performances des threads entre elles

Il existe de nombreuses méthodes d'implémentation Singleton, mais à partir de l'implémentation la plus simple (non chargée paresseusement, non thread-safe et). inefficace) à une implémentation lente, thread-safe et efficace, elles ont toutes des points communs de base :

  • Les classes Singleton n'ont qu'un seul constructeur privé sans paramètre

  • La classe est déclarée scellée (non obligatoire)

  • Il y a une variable statique dans la classe qui contient une référence à l'instance créée

  • La classe singleton fournira une méthode ou une propriété statique pour renvoyer une référence à l'instance créée (par exemple.GetInstance)

Plusieurs implémentations

Un non-thread-safe

//Bad code! Do not use!
public sealed class Singleton
{
  private static Singleton instance = null;
  private Singleton()
  {
  }

  public static Singleton instance
  {
    get
    {
      if (instance == null)
      {
        instance = new Singleton();
      }
      return instance;
    }
  }
}
Copier après la connexion
Cette méthode n'est pas Thread-safe, il y aura deux threads s'exécutant if (instance == null) en même temps et créer deux instances différentes. La nouvelle instance créée remplacera celle nouvellement créée, ce qui rendra la référence précédemment obtenue vide >

Deuxième implémentation simple thread-safe

Par rapport à. première implémentation, cette version ajoute un verrou sur l'instance. Le cadenas doit être verrouillé avant d'appeler l'instance. Cela évite les conflits de threads dans la première implémentation. Cependant, puisque le verrou est utilisé à chaque fois. l'instance est appelée et le coût d'appel du verrou est important, cette implémentation entraînera une certaine perte de performances

public sealed class Singleton
{
  private static Singleton instance = null;
  private static readonly object padlock = new object();

  Singleton()
  {
  }

  public static Singleton Instance
  {
    get
    {
      lock (padlock)
      {
        if (instance == null)
        {
          instance = new Singleton();
        }
        return instance;
      }
    }
  }
}
Copier après la connexion
Notez qu'ici, nous utilisons un nouveau cadenas d'instance d'objet privé pour implémenter l'opération de verrouillage, au lieu de directement. verrouiller le Singleton. Il existe des risques potentiels à verrouiller directement le type, car ce type est public, donc en théorie, il peut être appelé dans n'importe quel code. Le verrouiller directement entraînera des problèmes de performances et même des blocages. : En C#, le même thread peut effectuer plusieurs opérations sur un objet. Il est verrouillé une fois, mais si différents threads sont verrouillés en même temps, une attente de thread peut se produire ou un blocage grave peut se produire. Par conséquent, lorsque nous utilisons le verrouillage, essayez de verrouiller les variables privées dans la classe afin d'éviter la situation ci-dessus.

Implémentation thread-safe de vérification triple

Tout en garantissant la sécurité des threads, cette implémentation évite également l'opération de verrouillage à chaque fois que l'instance est appelée, ce qui sera le cas gagner un certain temps. Cependant, cette implémentation a aussi ses inconvénients :

public sealed calss Singleton
{
  private static Singleton instance = null;
  private static readonly object padlock = new object();

  Singleton()
  {
  }

  public static Singleton Instance
  {
    get
    {
      if (instance == null)
      {
        lock (padlock)
        {
          if (instance == null)
          {
            instance = new Singleton();
          }
        }
      }
      return instance;
    }
  } 
}
Copier après la connexion
1 ne fonctionnera pas en Java. (Vous pouvez voir le texte original pour les raisons spécifiques, mais je ne comprends pas grand-chose ici)

2 Les programmeurs peuvent facilement commettre des erreurs lorsqu'ils l'implémentent eux-mêmes. Si vous apportez vos propres modifications au code dans ce mode, soyez très prudent car la logique de double vérification est relativement complexe et il est facile de commettre des erreurs dues à une mauvaise réflexion.


Quatre implémentations thread-safe sans verrous


Cette implémentation est très simple et n'utilise pas de verrous, mais elle est toujours thread-safe. Une instance Singleton statique en lecture seule est utilisée ici. Elle créera une nouvelle instance lorsque le Singleton est appelé pour la première fois. La garantie de sécurité des threads lors de la création d'une nouvelle instance est directement contrôlée par .NET. opération. Et il ne sera créé qu’une seule fois dans un AppDomaing.

Cette implémentation présente également quelques inconvénients :
public sealed class Singleton
{
  //在Singleton第一次被调用时会执行instance的初始化
  private static readonly Singleton instance = new Singleton();

  //Explicit static consturctor to tell C# compiler 
  //not to mark type as beforefieldinit
  static Singleton()
  {
  }

  private Singleton()
  {
  }

  public static Singleton Instance
  {
    get
    {
      return instance;
    }
  }
}
Copier après la connexion

1 Le moment de la création de l'instance est inconnu et tout appel à Singleton créera l'instance à l'avance

2 Appels en boucle du constructeur statique . S'il y a deux classes, A et B, et que B est appelé dans le constructeur statique de A et que A est appelé dans le constructeur statique de B, ces deux classes formeront un appel circulaire, ce qui entraînera sérieusement le crash du programme. 3 Nous devons ajouter manuellement le constructeur statique de Singleton pour nous assurer que le type Singleton ne sera pas automatiquement ajouté avec l'attribut beforefieldinit pour garantir que l'instance sera créée lorsque Singleton est appelé pour la première fois. 4L'attribut readonly ne peut pas être modifié au moment de l'exécution. Si nous devons supprimer l'instance et recréer une nouvelle instance lorsque le programme est en cours d'exécution, cette méthode d'implémentation ne peut pas être satisfaite.



Cinq instanciation entièrement paresseuse

L'implémentation cinq est un wrapper pour l'implémentation quatre. Cela garantit que l'instance ne sera appelée que dans la méthode get d'Instance et ne sera initialisée qu'avant le premier appel. Il s'agit d'une version de l'implémentation 4 qui assure un chargement paresseux.

Six utilise le type Lazy de .NET4
public sealed class Singleton
{
  private Singleton()
  {
  }

  public static Singleton Instance 
  {
    get
    {
      return Nested.instance;
    }
  }

  private class Nested
  {
    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Nested()
    {
    }

    internal static readonly Singleton instance = new Singleton();
  }
}
Copier après la connexion

.NET4 ou supérieur prend en charge Lazy Le code garantit la sécurité des threads et les caractéristiques de chargement paresseux du singleton.

Différence de performances

Dans l'implémentation précédente, nous avons mis l'accent sur la sécurité des threads et le chargement paresseux du code. Cependant, en utilisation réelle, si l'initialisation de votre classe singleton ne prend pas de temps ou si la séquence d'initialisation ne provoque pas de bogues, l'initialisation retardée est une fonctionnalité superflue car le temps pris par l'initialisation est négligeable.

Dans les scénarios d'utilisation réels, si votre instance singleton est appelée fréquemment (comme dans une boucle), alors la consommation de performances causée par la garantie de la sécurité des threads mérite davantage d'attention.

Afin de comparer les performances de ces implémentations, j'ai fait un petit test, parcourant les singletons de ces implémentations 900 millions de fois, en appelant à chaque fois la méthode d'instance pour effectuer une opération count++, tous les millions. Sortie une fois , l'environnement d'exécution est Visual Studio pour Mac sur MBP. Les résultats sont les suivants :


线程安全性 延迟加载 测试运行时间(ms)
实现一 15532
实现二 45803
实现三 15953
实现四 不完全 14572
实现五 14295
实现六 22875

La méthode de test n'est pas rigoureuse, mais on voit quand même que la deuxième méthode est la plus longue car elle doit appeler lock à chaque fois, presque trois fois plus aussi longtemps que les autres. En deuxième position se trouve l'implémentation utilisant le type .NET Lazy, soit environ la moitié de plus que les autres. Les quatre autres ne présentent aucune différence évidente.

Résumé

En général, les différentes méthodes d'implémentation singleton mentionnées ci-dessus ne sont pas très différentes dans les performances informatiques actuelles, à moins que vous n'ayez besoin d'une concurrence particulièrement importante Seulement lorsque vous instance d’appel, vous devrez prendre en compte les problèmes de performances de verrouillage.

Pour les développeurs ordinaires, il suffit d'utiliser la méthode 2 ou la méthode 6 pour implémenter des singletons. Les méthodes 4 et 5 nécessitent une bonne compréhension du processus d'exécution et de l'implémentation en C#. Elles nécessitent certaines compétences et le temps qu'elles permettent de gagner. est encore limité.

Citation

La majeure partie de cet article est traduite de Implémentation du modèle Singleton en C#, avec une partie de ma propre compréhension ajoutée. C'est ce que j'ai vu lorsque j'ai recherché l'initialiseur de champ statique en lecture seule par rapport à l'initialisation du constructeur statique. Je voudrais exprimer mes remerciements aux deux auteurs ici.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Quelles sont les perspectives d'emploi du C# ? Quelles sont les perspectives d'emploi du C# ? Oct 19, 2023 am 11:02 AM

Que vous soyez débutant ou professionnel expérimenté, la maîtrise du C# ouvrira la voie à votre carrière.

Partagez plusieurs frameworks de projets open source .NET liés à l'IA et au LLM Partagez plusieurs frameworks de projets open source .NET liés à l'IA et au LLM May 06, 2024 pm 04:43 PM

Le développement des technologies d’intelligence artificielle (IA) bat son plein aujourd’hui et elles ont montré un grand potentiel et une grande influence dans divers domaines. Aujourd'hui, Dayao partagera avec vous 4 cadres de projets liés au modèle d'IA open source .NET LLM, dans l'espoir de vous fournir une référence. https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel est un kit de développement logiciel (SDK) open source conçu pour intégrer de grands modèles de langage (LLM) tels qu'OpenAI, Azure

Technologie d'optimisation des performances .NET pour les développeurs Technologie d'optimisation des performances .NET pour les développeurs Sep 12, 2023 am 10:43 AM

Si vous êtes un développeur .NET, vous devez être conscient de l'importance d'optimiser les fonctionnalités et les performances pour fournir des logiciels de haute qualité. En utilisant de manière experte les ressources fournies et en réduisant les temps de chargement des sites Web, vous créez non seulement une expérience agréable pour vos utilisateurs, mais vous réduisez également les coûts d'infrastructure.

Différences de performances entre le framework Java et le framework .NET Différences de performances entre le framework Java et le framework .NET Jun 03, 2024 am 09:19 AM

En termes de traitement des requêtes à haute concurrence, .NETASP.NETCoreWebAPI fonctionne mieux que JavaSpringMVC. Les raisons incluent : la compilation précoce AOT, qui réduit le temps de démarrage, une gestion plus raffinée de la mémoire, où les développeurs sont responsables de l'allocation et de la libération de la mémoire des objets.

C # .NET des questions et réponses d'entrevue: améliorez votre expertise C # .NET des questions et réponses d'entrevue: améliorez votre expertise Apr 07, 2025 am 12:01 AM

C # .NET Les questions et réponses d'entrevue comprennent les connaissances de base, les concepts de base et l'utilisation avancée. 1) Connaissances de base: C # est un langage orienté objet développé par Microsoft et est principalement utilisé dans le framework .NET. 2) Concepts de base: la délégation et les événements permettent des méthodes de liaison dynamiques, et LINQ fournit des fonctions de requête puissantes. 3) Utilisation avancée: la programmation asynchrone améliore la réactivité et les arbres d'expression sont utilisés pour la construction de code dynamique.

Tutoriel avancé C # .NET: Ace votre prochain entretien de développeur senior Tutoriel avancé C # .NET: Ace votre prochain entretien de développeur senior Apr 08, 2025 am 12:06 AM

L'entrevue avec C # Developer Senior Developer nécessite de maîtriser les connaissances de base telles que la programmation asynchrone, la LINQ et les principes de travail internes des frameworks .NET. 1. La programmation asynchrone simplifie les opérations par asynchronisation et attend pour améliorer la réactivité de l'application. 2.Linq exploite des données dans le style SQL et fait attention aux performances. 3. La CLR du cadre net gère la mémoire et la collecte des ordures doit être utilisée avec prudence.

C # .NET: Explorer les concepts de base et les principes fondamentaux de la programmation C # .NET: Explorer les concepts de base et les principes fondamentaux de la programmation Apr 10, 2025 am 09:32 AM

C # est un langage de programmation moderne et orienté objet développé par Microsoft et dans le cadre du .NET Framework. 1.C # prend en charge la programmation orientée objet (POO), y compris l'encapsulation, l'héritage et le polymorphisme. 2. La programmation asynchrone en C # est implémentée via Async et attend des mots clés pour améliorer la réactivité des applications. 3. Utilisez LINQ pour traiter les collections de données concisement. 4. Les erreurs courantes incluent les exceptions de référence NULL et les exceptions indexes hors gamme. Les compétences de débogage comprennent l'utilisation d'un débogueur et une gestion des exceptions. 5. L'optimisation des performances comprend l'utilisation de StringBuilder et d'éviter l'emballage et le déballage inutiles.

C # code dans .NET: Explorer le processus de programmation C # code dans .NET: Explorer le processus de programmation Apr 12, 2025 am 12:02 AM

Le processus de programmation de C # dans .NET comprend les étapes suivantes: 1) l'écriture de code C #, 2) la compilation dans un langage intermédiaire (IL) et 3) l'exécution par .NET Runtime (CLR). Les avantages de C # dans .NET sont sa syntaxe moderne, son système de type puissant et son intégration serrée avec le Framework .NET, adapté à divers scénarios de développement des applications de bureau aux services Web.

See all articles