Comment faire de la méthode statique "thread-safe"?
J'ai écrit une classe statique qui est un référentiel de certaines fonctions que je fais appel à partir d'une autre classe.
public static class CommonStructures
{
public struct SendMailParameters
{
public string To { get; set; }
public string From { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public string Attachment { get; set; }
}
}
public static class CommonFunctions
{
private static readonly object LockObj = new object();
public static bool SendMail(SendMailParameters sendMailParam)
{
lock (LockObj)
{
try
{
//send mail
return true;
}
catch (Exception ex)
{
//some exception handling
return false;
}
}
}
private static readonly object LockObjCommonFunction2 = new object();
public static int CommonFunction2(int i)
{
lock (LockObjCommonFunction2)
{
int returnValue = 0;
try
{
//send operation
return returnValue;
}
catch (Exception ex)
{
//some exception handling
return returnValue;
}
}
}
}
Question 1: Pour mon deuxième méthode CommonFunction2, dois-je utiliser une nouvelle statique de verrouillage c'est à dire LockObjCommonFunction2 dans cet exemple, ou puis-je réutiliser le même verrou de l'objet LockObj défini au début de la fonction.
Question 2: Est-il rien qui pourrait conduire à filetage questions connexes ou puis-je améliorer le code pour être sûr fil.
Point 3: Peut-il y avoir des problèmes en passant ordinaires de classe au lieu de struct.. dans cet exemple SendMailParameters( dont je fais usage de l'habillage de tous les paramètres, au lieu d'avoir plusieurs paramètres à la fonction SendMail)?
Ce qui concerne,
MH
Faire de toutes les méthodes de "thread-safe" ne garantit pas l'ensemble de l'application va être thread-safe ericlippert.com/2013/01/31/the-no-lock-deadlock
merci pour le partage de cet article. Eric est très bonne.
OriginalL'auteur user1961100 | 2013-06-07
Vous devez vous connecter pour publier un commentaire.
Si vous souhaitez synchroniser ces deux méthodes, alors vous devez utiliser la même serrure. Exemple, si thread1 est accéder à votre Method1, et thread2 est accéder à votre Method2 et vous vous en voulez de ne pas accéder simultanément les deux intérieur, utiliser la même serrure. Mais, si vous voulez juste pour restreindre l'accès simultané à juste soit Method1 ou 2, utilisation serrures différentes.
Rappelez-vous toujours que les ressources partagées (par exemple. les variables statiques, fichiers) ne sont pas thread-safe, car ils sont facilement accessibles par tous les threads, vous devez donc appliquer tout type de synchronisation (par l'intermédiaire de serrures, de signaux, de mutex, etc).
Aussi longtemps que vous appliquez la bonne synchronisations, il serait thread-safe. Pour les structures, regarder cette comme une référence.
La ligne de fond est que vous devez appliquer corriger les synchronisations pour rien que, dans une mémoire partagée. Aussi, vous devez toujours prendre note de la portée de la discussion, sont de frai et de l'état des variables de chaque méthode. - Ils changer l'état ou tout simplement dépendent de l'état interne de la variable? Le thread toujours créer un objet, bien qu'il soit statique ou partagés? Si oui, alors il doit être thread-safe. Sinon, si elle réutilise certaines ressources partagées, alors vous devez appliquer une synchronisation correcte. Et la plupart de tous, même sans une ressource partagée, les blocages, pourrait encore se produire, de sorte rappelez-vous les règles de base en C# pour éviter les blocages. P. S. grâce à Euphorique pour le partage de Eric Lippert de l'article.
Mais soyez prudent avec vos synchronisations. Autant que possible, de limiter leurs champs d'application que lorsque la ressource partagée est en cours de modification. Car il peut entraîner de gênant les goulots d'étranglement de votre application où la performance sera grandement affectée.
pas de soucis. heureux je l'ai aidé. aussi regarder Eric Lippert entrée sur les pas de lock blocages. il ne fait pas appel à des ressources partagées, mais encore il provoque un blocage. c'est assez intéressant.
OriginalL'auteur aiapatag
Vous pouvez réutiliser le même verrou de l'objet autant de fois que vous le souhaitez, mais cela signifie qu'aucune des zones de code entouré par la même de verrouillage peut être consulté dans le même temps par plusieurs threads. Si vous avez besoin de planifier en conséquence, et soigneusement.
Parfois, il est préférable d'utiliser un verrou de l'objet de multiples emplacement, s'il y a plusieurs fonctions de modifier le même tableau, par exemple. D'autres fois, plus d'une serrure objet est mieux, parce que même si un article de code est verrouillé, l'autre peut toujours courir.
Multi-thread de codage est tout au sujet de la planification soigneuse...
Être super duper sûr, au détriment de potentiellement écrit beaucoup plus lente code... vous pouvez ajouter un accesseur pour votre classe statique surround par une serrure. De cette façon vous pouvez vous assurer qu'aucune des méthodes de la classe ne sera jamais appelé par deux threads en même temps. C'est assez de force brute, et certainement un "non-non" pour les professionnels. Mais si vous êtes familier avec la façon dont ces choses fonctionnent, c'est pas un mauvais endroit pour commencer à apprendre.
Ce qui est un accesseur pour un statique class?
Je suppose que je devrais préciser... il allait vraiment être statique accesseur pour une classe (c'est à dire la création d'un "singleton'). Quelque chose comme: 'public Maclasse& INSTANCE() { static MyClass iInstance; <verrouillage auto> retour iInstance;}" et l'utilise pour accéder à la classe des interfaces.
Faire une recherche pour 'classe singleton" je suis sûr que apporterait de nombreuses façons de l'accomplir.
si l'on se réfère à "singleton", alors que c'est la restriction de l'accès à un objet n'est pas une classe. Ici nous avons affaire à une classe statique que vous souhaitez restreindre l'accès à
OriginalL'auteur
1) tout d'abord cela dépend de ce que vous voulez avoir:
Comme c'est (deux objets de verrou) - pas de deux threads s'exécutent de la même méthode, en même temps, mais ils peuvent exécuter les différentes méthodes en même temps.
Si vous changez d'avoir verrou unique objet a alors pas de deux threads de l'exécution de ces sous-rubriques de verrouillage partagé objet.
2) Dans votre extrait de code il n'y a rien qui me frappe comme mauvais - mais il n'y a pas beaucoup de code. Si votre dépôt des appels de méthodes à partir de lui-même, alors vous pouvez avoir un problème et il y a un monde de problèmes que vous pouvez rencontrer 🙂
3) Comme pour les structures, je n'aurais pas les utiliser. L'utilisation de classes c'est mieux/plus facile de cette façon, il est un autre sac de questions en liens avec les structures que vous n'avez pas besoin de ces problèmes.
comme pour les structures il y a quelques articles et même questions qui leur est dédié. Si vous me demandez, vous n'avez pas besoin de structure dans 99% des cas. Comme pour les problèmes de threading je faisais allusion à simple blocage lorsqu'sur st-1 fil d'une méthode (lock1) appelle une autre (lock2) et le 2-nd fil, l'ordre est inversé.
OriginalL'auteur Rafal
Le nombre de verrouiller des objets à utiliser dépend du type de données que vous essayez de protéger. Si vous avez plusieurs variables lecture/mise à jour sur plusieurs threads, vous devez utiliser un objet de verrouillage pour chaque variable indépendante. Donc, si vous avez 10 variables qui forment 6 variable indépendante groupes (autant que la façon dont vous avez l'intention de lire /écrire), vous devez utiliser 6 verrouiller des objets pour de meilleures performances. (Une variable indépendante est celle qui est en lecture /écrite sur plusieurs threads sans incidence sur la valeur des autres variables. Si 2 variables doivent être lus ensemble pour une action donnée, ils sont dépendants les uns des autres de sorte qu'ils doivent être verrouillés ensemble. J'espère que ce n'est pas trop confus.)
Régions verrouillées doit être aussi court que possible pour le maximum de performance à chaque fois que vous verrouillez une région de code, aucun autre thread ne peut entrer dans cette région jusqu'à ce que le verrou est libéré. Si vous avez un certain nombre de variables indépendantes, mais l'utilisation de trop peu de verrouiller des objets, votre performance de souffrir à cause de votre régions verrouillées va croître de plus.
Avoir plus de verrouiller des objets permet de plus le parallélisme étant donné que chaque thread peut lire /écrire une autre variable indépendante - fils ne ont à attendre les uns les autres, si ils tentent de lire /écrire les variables qui dépendent les uns des autres (et donc sont verrouillés par la même écluse de l'objet).
Dans votre code, vous devez être prudent avec votre
SendMailParameters
paramètre d'entrée - si c'est un type de référence (de la classe, pas struct), vous devez vous assurer que ses propriétés sont verrouillés ou qu'il n'est pas accessible sur plusieurs threads. Si c'est un type de référence, c'est juste un pointeur et sans verrouillage à l'intérieur de sa propriété getters /setters, plusieurs threads peut tenter de lire /écrire certaines des propriétés de la même instance. Si cela se produit, votreSendMail()
fonction peut retrouver à l'aide d'une instance endommagée. Il ne suffit pas de simplement avoir un verrou à l'intérieur deSendMail()
- propriétés et méthodes deSendMailParameters
doivent être protégés en tant que bien.OriginalL'auteur xxbbcc