Comment obtenir un compteur thread safe en C # avec les meilleures performances possibles?
C'est aussi simple que cela:
public static long GetNextValue()
{
long result;
lock (LOCK)
{
result = COUNTER++;
}
return result;
}
Mais existe-t-il des alternatives plus rapides?
Comme recommandé par d'autres, le Interlocked.Increment
Aura de meilleures performances que lock()
. Il suffit de jeter un coup d'œil à IL et à Assembly où vous verrez que Increment
se transforme en une instruction "lock lock" et que sa variable est directement incrémentée (x86) ou "ajoutée" à (x64).
Cette instruction "verrouillage du bus" verrouille le bus pour empêcher une autre CPU d'accéder au bus pendant que la CPU appelante effectue son opération. Maintenant, jetez un coup d'œil à l'IL de l'instruction C # lock()
. Ici, vous verrez les appels à Monitor
afin de commencer ou de terminer une section.
En d’autres termes, l’instruction .Net lock()
fait beaucoup plus que l’instrument .Net Interlocked.Increment
.
SO, si tout ce que vous voulez faire est d’incrémenter une variable, Interlock.Increment
Sera plus rapide. Passez en revue toutes les méthodes inter-verrouillées pour voir les différentes opérations atomiques disponibles et trouver celles qui répondent à vos besoins. Utilisez lock()
lorsque vous souhaitez effectuer des tâches plus complexes, telles que plusieurs incréments/décréments interdépendants, ou pour sérialiser l'accès à des ressources plus complexes que des entiers.
Je vous suggère d’utiliser l’incrémentation interlock intégrée de .NET dans la bibliothèque System.Threading.
Le code suivant incrémente une variable longue par référence et est totalement thread-safe:
Interlocked.Increment(ref myNum);
Source: http://msdn.Microsoft.com/en-us/library/dd78zt0c.aspx
Essayez avec Interlocked.Increment