C #: Que faire si une méthode statique est appelée à partir de plusieurs threads?

93

Dans mon application, j'ai une méthode statique qui est appelée à partir de plusieurs threads en même temps. Y a-t-il un risque que mes données soient mélangées?

Lors de ma première tentative, la méthode n'était pas statique et je créais plusieurs instances de la classe. Dans ce cas, mes données se sont mélangées d'une manière ou d'une autre. Je ne sais pas comment cela se produit, car cela n'arrive que parfois. Je suis toujours en train de déboguer. Mais maintenant, la méthode est statique sur je n'ai pas de problèmes pour l'instant. C'est peut-être juste de la chance. Je ne sais pas avec certitude.

TalkingCode
la source

Réponses:

96

Les variables déclarées à l'intérieur des méthodes (à l'exception possible des variables " capturées ") sont isolées, vous n'aurez donc aucun problème inhérent; cependant, si votre méthode statique accède à un état partagé, tous les paris sont désactivés.

Des exemples d'état partagé seraient:

  • champs statiques
  • objets accessibles à partir d'un cache commun (non sérialisé)
  • données obtenues via les paramètres d'entrée (et état de ces objets), s'il est possible que plusieurs threads touchent le (s) même (s) objet (s)

Si vous avez un état partagé, vous devez soit:

  • veillez à ne pas muter l'état une fois qu'il peut être partagé (mieux: utilisez des objets immuables pour représenter l'état, et prenez un instantané de l'état dans une variable locale - c'est-à-dire plutôt que de référencer à whatever.SomeDataplusieurs reprises, vous lisez whatever.SomeData une fois dans une variable locale, puis utilisez simplement la variable - notez que cela n'aide que pour l'état immuable!)
  • synchroniser l'accès aux données (tous les threads doivent se synchroniser) - lecteur / écrivain mutuellement exclusif ou (plus granulaire)
Marc Gravell
la source
1
@Diego - ce commentaire est-il destiné à moi ou à @Holli?
Marc Gravell
À Holli, juste pour ajouter quelques informations pratiques à votre réponse.
Diego Pereyra
1
@Marc Je ne peux pas être entièrement d'accord avec "Les variables déclarées à l'intérieur des méthodes (à l'exception possible des variables" capturées ") sont isolées". Considérez un descripteur de fichier qui est déclaré dans une méthode statique. Ensuite, un fil peut accéder à la poignée lorsqu'un autre fil l'utilise. Cela entraînera un comportement inattendu. Ou est-ce que votre variable «capturée» signifiait aussi «descripteur de fichier».
prabhakaran
9
@prabhakaran si un descripteur de fichier est une variable de méthode, il n'est étendu qu'à cet appelant. Tout autre appelant parlera à une variable différente (les variables de méthode sont par appel). Maintenant, l'accès au fichier sous-jacent est un problème distinct, mais qui n'est pas lié à c # ou .NET. Si le handle n'est pas partagé, on s'attendrait à une sorte de mutex / verrou si ce scénario est probable.
Marc Gravell
29

Oui, c'est juste de la chance. ;)

Peu importe que la méthode soit statique ou non, ce qui compte, c'est si les données sont statiques ou non.

Si chaque thread a sa propre instance distincte de la classe avec son propre ensemble de données, il n'y a aucun risque que les données soient mélangées. Si les données sont statiques, il n'y a qu'un seul ensemble de données et tous les threads partagent les mêmes données, il n'y a donc aucun moyen de ne pas les mélanger.

Lorsque vos données dans des instances séparées sont toujours mélangées, c'est probablement parce que les données ne sont pas vraiment séparées.

Guffa
la source
7
J'ai adoré cette ligne - It doesn't matter if the method is static or not, what matters is if the data is static or not. Juste pour ajouter, les variables locales déclarées dans le cadre d'une méthode statique ne font pas partie des données dont nous devons nous préoccuper dans le scénario donné.
RBT
très bonne réponse. J'ai beaucoup aidé.
Fractal
15

Les méthodes statiques devraient convenir à plusieurs threads.

Les données statiques, d'un autre côté, peuvent poser un problème car les tentatives d'accès aux mêmes données à partir de différents threads doivent être contrôlées pour s'assurer qu'un seul thread à la fois lit ou écrit les données.

Doug Ferguson
la source
2
Le mot clé ici est la synchronisation :-)
G. Stoynev
2
la lecture peut se produire simultanément, mais la lecture ET l'écriture simultanées entraîneront un comportement inattendu
Freestyle076
9

MSDN dit toujours:

Tous les membres statiques publics (partagés dans Visual Basic) de ce type sont thread-safe. Les membres d'instance ne sont pas garantis d'être thread-safe.

Edit: Comme le disent les gars ici, ce n'est pas toujours le cas, et cela s'applique clairement aux classes conçues de cette manière dans la BCL, pas aux classes créées par l'utilisateur où cela ne s'applique pas.

Marcote
la source
3
Phew! Enfin, j'ai compris la signification de cette note que l'on retrouve si fréquemment dans la documentation MSDN. Donc, fondamentalement, lorsque MS conçoit une méthode statique (où cette note est publiée) dans BCL, ils n'accèdent à aucune variable / membre / état qui est en dehors de la portée de cette méthode. Ils s'appuient entièrement sur des variables locales à portée de méthode uniquement pour implémenter la logique de cette méthode. Très heureux que vous ayez partagé.
RBT
@Marcote, le contraire n'est-il pas vrai? Les membres d'instance sont sûrs car il y en a un par instance. Cependant, les membres statiques ne sont pas thread-safe car ils sont partagés entre toutes les instances de cette classe? quora.com
Fractal
1
ça dépend. Je ne traiterais jamais un membre d'instance comme sûr par défaut. C'est pourquoi tout un ensemble de bibliothèques et pour éviter la corruption des données entre autres choses.
Marcote
1
d'accord, merci @Marcote. Je me rends compte lentement que j'ai beaucoup à apprendre.
Fractal