12
votes

Question sur l'utilisation de l'objet Monitor.tryenter et de verrouillage

Considérez la fonction suivante qui implémente un accès non bloquant à un seul thread.

object _locked = new object();


5 commentaires

JaredPar a fourni la réponse à votre problème. Mais votre logique semble être défectueuse - si vous entrez dans le moniteur avec _Locked = true, vous ne quitterez jamais le moniteur.


Oh certainement oui, merci vinayc


De plus, je pense que vous avez généralement un objet statique comme votre serrure.


@Chris. Pas dans mon cas. J'ai besoin de la synchronisation fournie pour l'instance de classe et non pour le type de classe. Ainsi, je n'ai pas besoin d'un objet de verrouillage statique.


Cool. Je pensais que cela pourrait être le cas mais je voulais vérifier que ce n'était pas juste une faute de frappe ou quelque chose. :)


3 Réponses :


29
votes

La raison pour laquelle est-ce que les méthodes moniteur prennent tous un paramètre system.Object . Lorsque vous passez dans un bool une case est nécessaire pour convertir en objet . L'opération de la boîte produit une nouvelle valeur System.Object pour chaque appel. Donc, le Tryenter et Quitter Les méthodes voient différents objets et résultent à l'exception.

Lorsque _Locké a été saisi sur objet Il n'y avait pas besoin d'une boîte. D'où le Tryenter et Quitter Les méthodes voient le même objet et peuvent fonctionner correctement.

Quelques autres commentaires sur le code

  • Tryenter doit être jumelé avec sortie dans tous les cas et pour la santé mentale que l'appel de sortie doit être enfin. Sinon vous invitez un scénario d'impasse
  • La variable _ / code> est défini uniquement sur false face à une exception. Si l'exécution ne produit pas d'exception, elle restera true et qu'aucun thread ne participera plus jamais au bloc si .

2 commentaires

O Yeah boxing sûr. Mais le type Bool n'est-il pas dérivé de System.Object? Donc, il est dérivé de l'objet, mais néanmoins quand une conversion à un objet est remplie quelque part une opération de boxe est utilisée? Cette déclaration est-elle correcte?


@Captain, lorsqu'un type de valeur de tout type, bool inclus, est utilisé dans un emplacement saisi sur System.Object ou une interface une opération de boxe aura lieu.



5
votes

Réglage du délai d'attente sur un moniteur à 0 peut aider à mettre en œuvre le comportement souhaité. Utilisez un objet déclaré globalement à verrouiller contre. xxx

.... xxx


5 commentaires

Monitor.frenter (MyLock, 0) est identique à moniteur.justiser (MyLock) autant que je puisse voir dans le réflecteur.


Pas de mon expérience. J'ai ajouté le ", 0" à la mienne et cela corrige le problème que j'avais.


@Andrew Objet statique var molock n'est pas une déclaration de variable valide.


@Derreckdean - surprenant que l'ajout , 0 corrigé un bug; Spec Monitor dit 0 est identique Comme omettant le paramètre: " si millisecondstimeout est égal à 0, cette méthode est équivalente à Tryenter (objet). "


@Tchelidze - Je suis d'accord, j'ai donc été modifié pour corriger la déclaration.



1
votes

Pour ajouter au succès ci-dessus - pour vous assurer que le verrouillage est relâché - TRYENTER () et EXIT () peuvent être enveloppés dans une classe personnalisée comme extension de objet em> prenant un délégué et un délai d'attente En tant que paramètre.

if (!_locked.TryEnter(() =>
{
    //Exclusive access code placed here..
}, 1000)) {
    throw new TimeoutException("Timeout waiting for exclusive access");
}


0 commentaires