web-dev-qa-db-fra.com

Pourquoi le verrouillage sur le même objet ne provoque-t-il pas un blocage?

Duplicata possible:
Verrous rentrants en C #

Si j'écris du code comme celui-ci:

class Program {
    static void Main(string[] args) {
        Foo();
        Console.ReadLine();
    }

    static void Foo() {
        lock(_lock) {
            Console.WriteLine("Foo");
            Bar();
        }
    }

    static void Bar() {
        lock(_lock) {
            Console.WriteLine("Bar");
        }
    }

    private static readonly object _lock = new object();
}

J'obtiens en sortie:

Foo
Bar

Je m'attendais à ce que cela se bloque, car Foo acquiert un verrou, puis attend que Bar acquière le verrou. Mais cela n'arrive pas.

Le mécanisme de verrouillage le permet-il simplement parce que le code est exécuté sur le même thread?

55
Eric

Pour le même thread, un verrou est toujours rentrant , donc le thread peut verrouiller un objet aussi souvent qu'il le souhaite.

77
thumbmunkeys

Parce que vous n'avez qu'un seul fil ici.

lock est un raccourci pour

bool lockWasTaken = false;
var temp = obj;
try { 
       Monitor.Enter(temp, ref lockWasTaken); 
       // your thread safe code
}
finally { if (lockWasTaken) Monitor.Exit(temp); }

Monitor.Enter acquérir le moniteur sur l'objet passé en paramètre. Si un autre thread a exécuté une entrée sur l'objet mais n'a pas encore exécuté la sortie correspondante, le thread actuel se bloquera jusqu'à ce que l'autre thread libère l'objet. Il est légal que le même thread invoque Enter plus d'une fois sans le bloquer ; cependant, un nombre égal d'appels de sortie doit être appelé avant que d'autres threads en attente sur l'objet ne se débloquent.

21
Sergey Berezovskiy

Un mot: serrure réentrante. Si un thread a déjà acquis un verrou, il n'attend pas s'il souhaite acquérir à nouveau le verrou. C'est très nécessaire sinon cela aurait pu transformer des fonctions récursives simples en cauchemar.!

9
pathfinder666

L'instruction lock est plus intelligente que cela, et elle est conçue pour empêcher cela. Le verrou est "possédé" par le thread une fois qu'il y est entré, donc chaque fois qu'il atteint une autre instruction lock qui verrouille le même objet, il se rendra compte qu'il a déjà accès à ce verrou.

5
Servy