12
votes

Peut-il y avoir des problèmes de concurrence lors de l'utilisation de la classe C # avec seulement des méthodes statiques et aucune variables?

ai-je compris correctement que tous les threads ont une copie des variables de la méthode dans leur propre pile, donc il n'y aura pas de problèmes lorsqu'une méthode statique est appelée à partir de différents threads?


4 commentaires

Si c'est une contrainte qui est étroitement - peut-être . Mais cela ne ressemble pas à une méthode très intéressante.


Je crois que ces problèmes se produiraient lors de l'opposé, par exemple, vous pourriez avoir une classe publique qui a également accès à des méthodes statiques, pouvez-vous donner un exemple de code exprimant exactement ce que votre confusion est ..?


Vous trouverez peut-être cela utile: CSHARPINDEPTH.COM/Articles/General/singleton.aspx


@Yuck pourquoi? Ce n'est pas parce qu'une méthode est pure , ne signifie pas que c'est ennuyeux. La programmation fonctionnelle traite presque exclusivement de telles méthodes et est toujours intéressante et puissante.


8 Réponses :


16
votes

oui et non. Si les paramètres sont des types de valeur, ils ont leurs propres copies. Ou si le type de référence est immuable, il ne peut pas être modifié et vous n'avez aucune question. Toutefois, si les paramètres sont des types de référence mutables, il reste encore des problèmes de sécurité threads possibles à considérer avec les arguments étant transmis.

Est-ce que cela a du sens? Si vous transmettez un type de référence comme argument, il est fait référence à une référence "par valeur", donc c'est une nouvelle référence qui renvoie à l'ancien objet. Ainsi, vous pourriez avoir deux threads différents potentiellement modifier le même objet de manière non fil-propre.

Si chacune de ces instances est créée et utilisée uniquement dans le fil en utilisant, puis les chances sont bas que vous obtiendriez un peu, mais je voulais juste souligner que tout simplement parce que vous utilisez simplement parce que vous utilisez simplement parce que vous utilisez Les méthodes statiques avec uniquement les locaux / paramètres ne sont pas une garantie de la sécurité de thread-sécurité (même avec l'instance, comme indiqué par Chris).


2 commentaires

+1 Pour noter que l'utilisation de statique (ou de son absence) ne garantit rien - les mêmes règles contiennent des méthodes non statiques.


@Chrisshain: Très vrai, j'aurais dû mentionner cela explicitement, j'espérais que c'était implicite.



2
votes

Il n'y a pas de garantie de ce type à moins que toutes les variables soient des types de référence immuables ou des types de valeur.

Si les variables sont des types de référence mutables, une synchronisation correcte doit être effectuée.

EDIT: Les variables mutables doivent être synchronisées uniquement si elles sont partagées entre les threads - les mutables déclarées localement qui ne sont pas exposées en dehors de la méthode ne doivent pas nécessairement être synchronisées.


1 commentaires

Les références mutables déclarées et utilisées localement n'ont pas besoin de synchronisation.



0
votes

Oui, à moins que des méthodes n'utilisent uniquement la variable de portée locale et aucune variable glovante , donc il n'y a pas de moyen aucune de ces méthodes peut Impact sur l'état de n'importe quel objet, si c'est vrai , vous n'avez aucun problème à l'utiliser dans Multithreading. Je dirais que même, dans cette situation, statique ils ou non, n'est pas pertinent.


0 commentaires

0
votes

S'ils sont des variables locales à la méthode, vous n'avez rien à craindre. Assurez-vous simplement de ne pas passer des paramètres par référence ou d'accéder à des variables globales et de les modifier dans différents threads. Ensuite, vous serez en difficulté.


0 commentaires

0
votes

statique peut faire référence à des données dans statiques dans leur classe ou en dehors de celui-ci - ce qui peut ne pas être le fil de sécurité.

Donc, finalement, la réponse à votre question est "non", car il peut y avoir des problèmes, bien qu'il n'y aura pas.


0 commentaires

0
votes

Deux threads doivent toujours être capables de fonctionner sur le même objet soit par l'objet étant transmis à des méthodes sur différents threads en tant que paramètres, ou si un objet peut être accédé à l'échelle mondiale via Singleton ou dans tout ce que tous les paris sont désactivés.

marque


0 commentaires

10
votes

ai-je compris correctement que tous les threads ont une copie des variables de la méthode dans leur propre pile, donc il n'y aura pas de problèmes lorsqu'une méthode statique est appelée à partir de différents threads? P>

non. P>

Tout d'abord, il est faux que "tous les threads ont une copie des variables locales de la méthode dans leur propre pile". Une variable locale n'est générée que sur la pile lorsqu'elle a une courte durée de vie; Les variables locales peuvent avoir une longue durée de vie arbitrairement longue si elles sont (1) des variables extérieures fermées, (2) déclarées dans un bloc d'itérateur, ou (3) déclarée dans une méthode asynchrone. P>

dans tous ces cas Une variable locale créée par une activation d'une méthode sur un thread peut ensuite être mutée par plusieurs threads. Ce faisant n'est pas threadsafe. P>

Deuxièmement, il existe de nombreux problèmes possibles lors de l'appel des méthodes statiques de différents threads. Le fait que les variables locales sont parfois allouées sur la pile ne rend pas par magie l'accès à la mémoire partagée par des méthodes statiques soudainement correctes. P>

Peut y avoir des problèmes de concurrence lors de l'utilisation de la classe C # avec uniquement des méthodes statiques et aucune variables? P> BlockQuote>

Je suppose que vous voulez dire "pas de variables statiques" et non "Pas de variables locales". P>

absolument, il peut être fort>. Par exemple, voici un programme sans variables statiques, aucune méthode non statique, aucun objet créé à part le deuxième fil, et une seule variable locale pour contenir une référence à ce fil. Aucune des méthodes autres que le cctor ne ne font rien du tout em>. Ce programme impasse. strong> Vous ne pouvez pas supposer que simplement parce que votre programme est simple, il ne contient aucun bogue de filetage! P>

Exercice au lecteur: Décrivez pourquoi ce programme qui semble contenir non verrouille réellement des blocages. P>

class MyClass
{
  static MyClass() 
  {
      // Let's run the initialization on another thread!
      var thread = new System.Threading.Thread(Initialize);
      thread.Start();
      thread.Join();
  }

  static void Initialize() 
  { /* TODO: Add initialization code */ }

  static void Main() 
  { }
}


4 commentaires

Le CORT Statique est garanti de terminer avant tout membre statique (la méthode initialiser dans ce cas) est autorisée à exécuter, mais la CTOR est occupée à attendre le fil qui attend ce CTOR.


@Albinsunnanbo: Vous avez la bonne idée. Mais bien sûr, si le cctor appelé initialise sans reprocher un thread, l'appel serait autorisé même s'il s'agit d'un membre statique exécutant avant que le constructeur statique ait fini de fonctionner. Un moyen plus précis d'indiquer le problème est le suivant: si un deuxième fil tente d'accéder à un élément statique pendant que le cctor s'exécute sur le premier thread, le deuxième thread ignore le cctor et attend le premier fil de finition avant d'accéder à la membre statique. Mais puisque dans ce cas, le premier thread attend sur la seconde, impasse.


semble raisonnable. Le problème de verrouillage mort n'est pas évident à partir du Page MSDN , mais le C # Spécification 17.11 au moins donne un indice en notant "au plus une fois dans un domaine d'application donné".


Je pense que cela devrait donc concevoir une sorte d'avertissement / filtre automatique sur la "variable locale sur la pile" questions / réponses.



0
votes

comme un addendum aux réponses sur la raison pour laquelle les méthodes statiques ne sont pas nécessairement du thread-coffre-fort, il convient de considérer pourquoi ils pourraient être, et pourquoi ils sont souvent.

La première raison pour laquelle ils pourraient être, je pense que le Une sorte de cas que vous pensiez à: p> xxx pré>

Cette fonction pure est le fil-coffre-fort car il n'y a aucun moyen d'affecter le code sur un autre thread, les locaux x code> et y code> restez local sur les rachats qu'elles sont activées, ne sont pas stockées dans un lieu commun, capturé dans un délégué ou laissant autrement le contexte purement local. P>

Il est toujours à noter que les combinaisons d'opérations de fil-sécurité peuvent être sans thread-coffre-fort (par exemple, faire une lecture de thread-coffre-fort de savoir si un dictionnaire simultané a une clé suivie d'une lecture de la valeur de thread-sûre de cette clé, est non thread-coffre-fort comme l'état peut changer entre ces deux opérations de sécurité). Les membres statiques ont tendance à ne pas être des membres qui peuvent être combinés de manière non thérapeutique de manière non thread-sécurité afin d'éviter cela. P>

Une méthode statique peut également garantir sa propre sécurité: P>

public object GetCachedEntity(string key)
{
  object ret;
  return _cache.TryGetValue(key, out ret) ? ret : null; //_cache is known to be thread-safe in itself!
}


0 commentaires