Je viens de me rendre compte qu'à un endroit de mon code, j'ai l'instruction return à l'intérieur de la serrure et parfois à l'extérieur. Lequel est le meilleur?
1)
void example()
{
lock (mutex)
{
//...
}
return myData;
}
2)
void example()
{
lock (mutex)
{
//...
return myData;
}
}
Lequel dois-je utiliser?
c#
.net
multithreading
mutex
Patrick Desjardins
la source
la source
Réponses:
Essentiellement, ce qui rend le code plus simple. Le point de sortie unique est un bel idéal, mais je ne déformerais pas le code juste pour y parvenir ... Et si l'alternative est de déclarer une variable locale (en dehors du verrou), de l'initialiser (à l'intérieur du verrou) et puis le renvoyer (à l'extérieur de la serrure), alors je dirais qu'un simple "return foo" à l'intérieur de la serrure est beaucoup plus simple.
Pour montrer la différence dans IL, permet de coder:
(notez que je soutiendrais volontiers que
ReturnInside
c'est un peu plus simple / plus propre de C #)Et regardez l'IL (mode de libération, etc.):
Donc au niveau IL ils sont [donner ou prendre quelques noms] identiques (j'ai appris quelque chose ;-p). En tant que tel, la seule comparaison raisonnable est la loi (très subjective) du style de codage local ... Je préfère
ReturnInside
pour la simplicité, mais je ne serais pas excité non plus.la source
ret
intérieur d'une.try
région.Cela ne fait aucune différence; ils sont tous deux traduits de la même manière par le compilateur.
Pour clarifier, l'un ou l'autre est effectivement traduit en quelque chose avec la sémantique suivante:
la source
Je mettrais certainement le retour dans la serrure. Sinon, vous risquez qu'un autre thread entre dans le verrou et modifie votre variable avant l'instruction de retour, ce qui fait que l'appelant d'origine reçoit une valeur différente de celle attendue.
la source
Ça dépend,
Je vais aller à contre-courant ici. Je reviendrais généralement à l'intérieur de la serrure.
Habituellement, la variable mydata est une variable locale. J'aime déclarer des variables locales pendant que je les initialise. J'ai rarement les données pour initialiser ma valeur de retour en dehors de mon verrou.
Donc, votre comparaison est en fait erronée. Bien que, idéalement, la différence entre les deux options soit celle que vous aviez écrite, ce qui semble donner un clin d'œil au cas 1, en pratique, c'est un peu plus laid.
contre.
Je trouve que le cas 2 est considérablement plus facile à lire et plus difficile à bousiller, en particulier pour les courts extraits.
la source
Si vous pensez que la serrure à l'extérieur est meilleure, mais faites attention si vous finissez par changer le code en:
Si f () doit être appelé avec le verrou maintenu, il doit évidemment être à l'intérieur du verrou, car il est logique de conserver les retours à l'intérieur du verrou pour la cohérence.
la source
Pour ce que ça vaut, la documentation sur MSDN a un exemple de retour de l'intérieur de la serrure. D'après les autres réponses ici, cela semble être assez similaire à IL mais, pour moi, il semble plus sûr de revenir de l'intérieur du verrou, car vous ne courez pas le risque qu'une variable de retour soit écrasée par un autre thread.
la source
Pour faciliter la lecture du code par les autres développeurs, je suggère la première alternative.
la source
lock() return <expression>
déclarations toujours:1) entrer dans la serrure
2) rend le stockage local (thread-safe) pour la valeur du type spécifié,
3) remplit le magasin avec la valeur renvoyée par
<expression>
,4) Verrouillage de sortie
5) retourner le magasin.
Cela signifie que la valeur, renvoyée par l'instruction de verrouillage, est toujours "cuite" avant le retour.
Ne t'inquiète
lock() return
pas, n'écoute personne ici))la source
Remarque: je pense que cette réponse est factuellement correcte et j'espère qu'elle est également utile, mais je suis toujours heureux de l'améliorer sur la base de commentaires concrets.
Pour résumer et compléter les réponses existantes:
La réponse acceptée montre que, quelle que soit la forme de syntaxe que vous choisissez dans votre code C # , dans le code IL - et donc au moment de l'exécution -
return
cela ne se produit qu'après la libération du verrou.return
intérieur dulock
bloc par conséquent, à proprement parler, dénature le flux de contrôle [1] , il est syntaxiquement pratique en ce qu'il évite le besoin de stocker la valeur de retour dans un aux. variable locale (déclarée à l'extérieur du bloc, afin qu'elle puisse être utilisée avec unereturn
à l'extérieur du bloc) - voir la réponse d'Edward KMETT .Séparément - et cet aspect est accessoire à la question, mais peut toujours être intéressant ( la réponse de Ricardo Villamil essaie d'y répondre, mais de manière incorrecte, je pense) - en combinant une
lock
déclaration avec unereturn
déclaration - c'est-à-dire obtenir une valeurreturn
dans un bloc protégé de accès simultané - "protège" de manière significative la valeur renvoyée dans la portée de l' appelant uniquement si elle n'a pas réellement besoin d'être protégée une fois obtenue , ce qui s'applique dans les scénarios suivants:Si la valeur renvoyée est un élément d'une collection qui n'a besoin de protection qu'en termes d' ajout et de suppression d' éléments, pas en termes de modifications des éléments eux - mêmes et / ou ...
... si la valeur renvoyée est une instance d'un type valeur ou d'une chaîne .
Dans tous les autres cas, le verrouillage doit être effectué par l' appelant , pas (seulement) à l'intérieur de la méthode.
[1] Theodor Zoulias souligne que ce qui est techniquement vrai aussi pour placer l'
return
intérieurtry
,catch
,using
,if
,while
,for
, ... déclarations; cependant, c'est le but spécifique de lalock
déclaration qui est susceptible d'inviter à un examen minutieux du véritable flux de contrôle, comme en témoigne cette question qui a été posée et a reçu beaucoup d'attention.[2] L'accès à une instance de type valeur crée invariablement une copie locale de thread sur la pile; même si les chaînes sont techniquement des instances de type référence, elles se comportent effectivement comme des instances de type valeur similaire.
la source
lock
, et tirez une signification du placement de la déclaration de retour. Ce qui est une discussion sans rapport avec cette question à mon humble avis. De plus, je trouve l'utilisation de "déformer" assez dérangeante. Si retour d'unelock
manière erronée le flux de contrôle, la même chose pourrait être dit pour le retour d'untry
,catch
,using
,if
,while
,for
et toute autre construction de la langue. C'est comme dire que le C # est truffé de fausses déclarations de flux de contrôle. Jesus ...try
,if
... je ne tends personnellement à y penser, mais dans le contexte delock
, en particulier, la question se posait pour moi - et si elle ne se posait pas pour les autres aussi, cette question n'aurais jamais été demandé , et la réponse acceptée ne serait pas allée très loin pour enquêter sur le vrai comportement.