7
votes

Pourquoi verrouillage () n'est pas autorisé, mais surveiller.enter () autorisé?

Pour le code suivant, je reçois une erreur de temps de compilation, *

'int' n'est pas un type de référence comme requis par l'instruction de verrouillage xxx

mais aucune erreur pour cela: xxx

Je comprends qu'un type de valeur ne doit pas être utilisé pour le verrouillage dû aux complications découlant de la boxe. Mais, alors pourquoi fonctionne-t-il avec le moniteur?


0 commentaires

5 Réponses :


16
votes

La raison pour laquelle est-ce que la serrure est une construction de langue et un compilateur choisit d'imposer une sémantique supplémentaire sur l'expression. Monitor.enter est simplement un appel de méthode et le compilateur C # ne case pas particulièrement l'appel de quelque manière que ce soit et que cela passe donc une résolution normale sur la surcharge et la boxe.


0 commentaires

0
votes

Je dirais que c'est parce que moniteur.enter () est un appel de méthode, de sorte que le compilateur effectue la boxe automatiquement, tandis que verrouillage () est un élément syntaxique, Donc, le compilateur peut vérifier et lancer une erreur sur les types de valeur.


2 commentaires

Je ne pense pas qu'il y ait une vérification. N'est pas verrouillage juste développé avec un monito.enter dans un bloc d'essai et moniteur.exit dans le bloc enfin.


Non, il est étendu à cela, mais d'abord le compilateur Spots si vous êtes stupide sur le chemin ...



13
votes

Vous ne devez absolument pas utiliser moniteur.enter sur un int . La raison pour laquelle cela fonctionne est que le int est en boîte, alors que si vous stockez une référence à la valeur en boîte, vous verrez un objet temporaire, ce qui signifie que vous ne pouvez pas appeler moniteur.exit sans obtenir une exception.

La manière recommandée de faire le verrouillage consiste à créer un objet loadonly et verrouille dessus. Pour une méthode statique, vous pouvez utiliser un objet statique .


0 commentaires

4
votes

juste hors de curiosité, que faites-vous avec la variable 'I' qui l'oblige à être verrouillée? Il peut être plus efficace d'utiliser la classe verrouillée si tout votre part est un incrément ou quelque chose: xxx

La classe verrouillée est l'outil de synchronisation de fil de poids la plus léger qui fournit et pour des incréments simples , décréments, lit ou échanges, c'est la meilleure option.

Si vous essayez de synchroniser un bloc de comportement, je créerais simplement un objet pouvant être utilisé comme racine de synchronisation: xxx


1 commentaires

Purement hors d'intérêt ... je suis conscient de la classe verrouillée. Merci.



6
votes

La spécification du compilateur définit Le comportement de verrouillage comme si :

Le type d'heure de compilation de l'expression d'un relevé de verrouillage doit être un paramètre de type de référence ou un paramètre de type (§25.1.1) connu pour être un type de référence. C'est une erreur de compilation pour la Compilez le type d'heure de l'expression pour désigner un type de valeur.

Il définit ensuite ce qu'il est équivalent à tant que cela compile

Etant donné que moniteur.exit est juste un appel de méthode sans aucune contrainte, il n'empêchera pas le compilateur de la boxe automatiquement de l'INT et de passer sa méthode joyeuse (et très) incorrecte.

verrouillage n'est pas simplement syntaxique sucre de la même manière foreach n'est pas simplement le sucre syntaxique. La transformation IL résultante est pas présentée au reste du code comme si c'était ce qui avait été écrit.

in foreach Il est illégal de modifier la variable d'itération (malgré le niveau d'IL au niveau de l'IL dans le code de sortie résultant qui l'empêcherait). En verrouillage, le compilateur empêche la compilation des types de valeur connus de la compilation, en dépit d'une fois que l'IL résultant ne se souciait pas de cela.

comme un de côté:
En théorie, le compilateur pourrait être «béni» avec une connaissance intime de cette méthode (et d'autres) de sorte que cela aperçu des cas évidents de cet événement, mais il est fondamentalement impossible pour toujours repérer cela au moment de la compilation (considérer un objet passé d'une autre méthode, assemblage ou par réflexion), si vous souciez de repérer de tels cas, serait probablement contre-productif.

Plus le compilateur connaît les internes de l'API, plus vous aurez des problèmes si vous souhaitez modifier l'API à l'avenir.

Il est possible que l'on puisse ajouter une surcharge de moniteur. Cela se conformerait aux spécifications du moniteur (même si elle serait probablement hideuse) mais causerait des problèmes énormes pour que le compilateur plus âgé empêche encore une opération devenue légale.


0 commentaires