Comme recommandé par d'autres, le Interlocked.Increment
aura de meilleures performances que lock()
. Jetez un coup d'œil à l'IL et à l'assembly où vous verrez que cela Increment
se transforme en une instruction "bus lock" et sa variable est directement incrémentée (x86) ou "ajoutée" à (x64).
Cette instruction "bus lock" 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 œil à l' lock()
IL de l'instruction C # . Ici, vous verrez des appels Monitor
pour commencer ou terminer une section.
En d'autres termes, l' lock()
instruction .Net fait beaucoup plus que le .Net Interlocked.Increment
.
Donc, si tout ce que vous voulez faire est d'incrémenter une variable, ce Interlock.Increment
sera plus rapide. Passez en revue toutes les méthodes Interlocked pour voir les différentes opérations atomiques disponibles et pour trouver celles qui correspondent à vos besoins. À utiliser lock()
lorsque vous souhaitez effectuer des opérations plus complexes, telles que plusieurs incréments / décrémentations interdépendants, ou pour sérialiser l'accès à des ressources plus complexes que des entiers.
Je vous suggère d'utiliser l'incrément de verrouillage intégré de .NET dans la bibliothèque System.Threading.
Le code suivant incrémentera une variable longue par référence et est totalement thread-safe:
Source: http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx
la source
Essayez avec Interlocked.
la source
Comme déjà mentionné l'utilisation
Interlocked.Increment
Exemple de code de MS:
L'exemple suivant détermine combien de nombres aléatoires compris entre 0 et 1 000 sont nécessaires pour générer 1 000 nombres aléatoires avec une valeur médiane. Pour garder une trace du nombre de valeurs médianes, une variable, midpointCount, est définie égale à 0 et incrémentée chaque fois que le générateur de nombres aléatoires renvoie une valeur médiane jusqu'à ce qu'elle atteigne 10 000. Étant donné que trois threads génèrent les nombres aléatoires, la méthode Increment (Int32) est appelée pour garantir que plusieurs threads ne mettent pas à jour midpointCount simultanément. Notez qu'un verrou est également utilisé pour protéger le générateur de nombres aléatoires et qu'un objet CountdownEvent est utilisé pour garantir que la méthode Main ne termine pas l'exécution avant les trois threads.
L'exemple suivant est similaire au précédent, sauf qu'il utilise la classe Task au lieu d'une procédure de thread pour générer 50 000 entiers intermédiaires aléatoires. Dans cet exemple, une expression lambda remplace la procédure de thread GenerateNumbers et l'appel à la méthode Task.WaitAll élimine le besoin de l'objet CountdownEvent.
https://docs.microsoft.com/en-us/dotnet/api/system.threading.interlocked.increment?view=netcore-3.0
la source