Existe-t-il des règles / directives générales sur ce qui rend une méthode thread-safe? Je comprends qu'il y a probablement un million de situations ponctuelles, mais qu'en est-il en général? Est-ce simple?
- Si une méthode accède uniquement aux variables locales, elle est thread-safe.
Est-ce que c'est ça? Cela s'applique-t-il également aux méthodes statiques?
Une réponse, fournie par @Cybis, était:
Les variables locales ne peuvent pas être partagées entre les threads car chaque thread obtient sa propre pile.
Est-ce également le cas des méthodes statiques?
Si une méthode reçoit un objet de référence, cela brise-t-il la sécurité des threads? J'ai fait quelques recherches, et il y a beaucoup de choses sur certains cas, mais j'espérais être en mesure de définir, en utilisant seulement quelques règles, des directives à suivre pour m'assurer qu'une méthode est thread-safe.
Donc, je suppose que ma question ultime est: "Y a-t-il une courte liste de règles qui définissent une méthode thread-safe? Si oui, quelles sont-elles?"
EDIT
Beaucoup de bons points ont été soulevés ici. Je pense que la vraie réponse à cette question est: "Il n'y a pas de règles simples pour garantir la sécurité des threads." Cool. Bien. Mais en général, je pense que la réponse acceptée fournit un bon résumé court. Il y a toujours des exceptions. Ainsi soit-il. Je peux vivre avec ça.
la source
Réponses:
Si une méthode (instance ou statique) fait uniquement référence à des variables de portée dans cette méthode, elle est thread-safe car chaque thread a sa propre pile:
Dans ce cas, plusieurs threads peuvent appeler
ThreadSafeMethod
simultanément sans problème.Cela est également vrai si la méthode appelle une autre méthode de classe qui ne fait référence qu'à des variables de portée locale:
Si une méthode accède à des propriétés ou des champs (d'état de l'objet) (instance ou statique), vous devez utiliser des verrous pour vous assurer que les valeurs ne sont pas modifiées par un thread différent.
Vous devez être conscient que tous les paramètres transmis à la méthode qui ne sont ni un struct ni immuable peuvent être mutés par un autre thread en dehors de la portée de la méthode.
Pour garantir une concurrence d'accès appropriée, vous devez utiliser le verrouillage.
pour plus d'informations, consultez la référence C # de l'instruction de verrouillage et ReadWriterLockSlim .
lock est surtout utile pour fournir une fonctionnalité à la fois,
ReadWriterLockSlim
est utile si vous avez besoin de plusieurs lecteurs et d'écrivains uniques.la source
private string someValue;
n'est passtatic
si chaque instance obtiendra une copie distincte de cette variable. Alors, pouvez-vous expliquer en quoi ce n'est pas thread-safe?Thing
classe accessible par plusieurs threadsAbsolument pas. Vous pouvez écrire un programme avec une seule variable locale accessible à partir d'un seul thread qui n'est cependant pas threadsafe:
https://stackoverflow.com/a/8883117/88656
Absolument pas.
Absolument pas. La caractéristique distinctive d'une variable locale est qu'elle n'est visible que depuis l'étendue locale , et non qu'elle est allouée sur le pool temporaire . Il est parfaitement légal et possible d'accéder à la même variable locale à partir de deux threads différents. Vous pouvez le faire en utilisant des méthodes anonymes, des lambdas, des blocs d'itérateur ou des méthodes asynchrones.
Absolument pas.
Peut être.
Vous allez devoir apprendre à vivre avec la déception. C'est un sujet très difficile.
Nan. Comme vous l'avez vu dans mon exemple plus tôt, une méthode vide peut être non thread-safe . Vous pourriez aussi bien demander "existe-t-il une courte liste de règles garantissant qu'une méthode est correcte ". Non, il n'y en a pas. La sécurité des fils n'est rien de plus qu'un type d'exactitude extrêmement compliqué.
De plus, le fait que vous posiez la question indique votre malentendu fondamental sur la sécurité des fils. La sécurité des threads est une propriété globale et non locale d'un programme. La raison pour laquelle il est si difficile de bien faire est que vous devez avoir une connaissance complète du comportement de threading de l'ensemble du programme afin d'assurer sa sécurité.
Encore une fois, regardez mon exemple: chaque méthode est triviale . C'est la façon dont les méthodes interagissent les unes avec les autres à un niveau «global» qui rend le programme dans l'impasse. Vous ne pouvez pas regarder toutes les méthodes et les cocher comme "sûres" et vous attendre à ce que tout le programme soit sûr, pas plus que vous ne pouvez en conclure que parce que votre maison est faite de briques à 100% non creuses, la maison est également non creux. Le creux d'une maison est une propriété globale de l'ensemble, pas un agrégat des propriétés de ses parties.
la source
class C { public static Func<int> getter; public static Action<int> setter; public static void M() { int x = 0; getter = ()=>x; setter = y=>{x=y;};} }
Appelez M (), puis appelez C.getter et C.setter sur deux threads différents. La variable locale peut maintenant être écrite et lue sur deux threads différents, même s'il s'agit d'un local. Encore une fois: la caractéristique déterminante d'une variable locale est qu'elle est locale , non qu'elle se trouve sur la pile du thread .Il n'y a pas de règle absolue.
Voici quelques règles pour sécuriser les threads de code dans .NET et pourquoi ce ne sont pas de bonnes règles:
lock
sur une chose commune. Tous les verrous doivent être effectués dans le même ordre. Cela rendra le thread de code sûr, mais il sera incroyablement lent, et vous pourriez aussi bien ne pas utiliser plusieurs threads.Il n'y a pas de règle qui rend le thread de code sûr, la seule chose que vous pouvez faire est de vous assurer que votre code fonctionnera quel que soit le nombre de fois qu'il est activement exécuté, chaque thread peut être interrompu à tout moment, chaque thread étant en cours son propre état / emplacement, et ce pour chaque fonction (statique ou non) qui accède aux objets communs.
la source
Il doit être synchronisé, à l'aide d'un verrou d'objet, sans état ou immuable.
lien: http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
la source