pourquoi cette instruction de locking ne fonctionne-t-elle pas?

class Program { static object test = new object(); static void Main(ssortingng[] args) { new Program().test2(); Console.ReadKey(); } public void test1() { lock (test) { Console.WriteLine("test1"); } } public void test2() { lock (test) { test1(); Console.WriteLine("test2"); } } } 

Le code ci-dessus est-il censé d’abord terminer les instructions dans l’instruction lock de test2 (), puis accéder à test1 ()? (ie la sortie n’est-elle pas supposée être comme ça?: test2 test1)

Un moniteur est re-entrant sur le même thread. Assez important pour éviter un blocage accidentel, votre code se figerait solidement s’il n’avait pas ce comportement.

Un mutex est également ré-entrant, un sémaphore ne l’est pas.

La mise en œuvre est assez simple. Un moniteur stocke deux informations. Le propriétaire Thread.ManagedId du thread qui l’a entré et un compteur qui compte le nombre de fois où il a été entré. Ainsi, le premier verrou peut entrer car il ne fait pas partie du propriétaire, il atsortingbue le propriétaire à votre thread et le compte à 1. Le second verrou est autorisé à entrer puisque l’ID du thread correspond, le compte passe à 2. À la fin de la deuxième locking, le compte décroît à 1 à nouveau. À la fin de la première, le compte décroît à 0 et réinitialise le propriétaire.

La séquence des événements (l’identification représente la stack d’appel ou les opérations logiques) est la suivante:

  • Appels principaux test2
    • test2 tente d’acquérir le moniteur associé à l’object à tester (début de l’instruction de lock )
      • Le moniteur est actuellement non possédé. Succès!
      • Le fil actuel “possède” maintenant ce moniteur, avec un compte de 1
    • test2 appelle test1
      • test1 tente d’acquérir le moniteur pour l’object à tester (début de l’instruction de lock )
        • Le moniteur appartient actuellement … mais par le thread actuel. Succès!
        • Le thread actuel “possède” toujours le moniteur, avec un compte de 2
      • test1 imprime “test1”
      • test1 libère le moniteur (fin de l’instruction de lock )
        • Le thread actuel “possède” toujours le moniteur, avec un compte de 1
      • test1 retourne
    • test2 imprime “test2”
    • test2 libère le moniteur (fin de l’instruction de lock )
      • Le moniteur est maintenant non possédé (donc un autre thread pourrait l’acquérir)
    • test2 retourne

Il est important de noter que les moniteurs sont ré-entrants – si le thread actuel possède déjà le moniteur, une autre tentative pour l’acquérir augmentera simplement le nombre, plutôt que le blocage.

Si les moniteurs n’étaient pas ré-entrants, la sortie ne serait pas “test2, test1” – ce serait simplement une impasse.

Le locking n’est pas censé être utilisé dans des scénarios à un seul thread. Son but est d’être utilisé dans les appels inter-thread aux mêmes méthodes ou instances d’object.

Le comportement que vous remarquez est normal.

Vous voudrez généralement synchroniser l’access aux ressources (variables, collections, etc.) lorsque deux ou plusieurs threads peuvent y accéder simultanément.