2009-02-19 5 views
4

Donc, ce n'est pas mon code et a été raccourci pour montrer le comportement, mais il donne des résultats très inattendus.Weird lock() comportement avec foreach

J'ai deux fonctions dans une classe et un verrou

object mylock = new object(); 
List<string> temp = new List<string>(); 

Func1(string) 
{ 
    lock(mylock) 
    { 
    temp.Add(string); 
    } 
} 

Func2() 
{ 
    lock(mylock) 
    { 
    temp.ForEach(p => Func1(p)); 
    } 
} 

Maintenant, je sais que cela n'a aucun sens, mais quand Func2 est appelée, ne devrait pas Func1 impasse? Dans notre cas, il s'exécute. Merci.

Répondre

13

Non, il ne devrait pas être bloqué.

Func1 peut obtenir le verrou si elle est appelée par une personne qui détient déjà le verrou (comme Func2)

Le MSDN doc for lock explique:

« Alors qu'un verrou d'exclusion mutuelle est tenue, le code d'exécution dans le même Le thread d'exécution peut également obtenir et libérer le verrou, mais le code s'exécutant dans d'autres threads est bloqué jusqu'à l'obtention du verrou. "

Le but du verrou est d'empêcher différents threads d'accéder à la même ressource. Func1 et Func2 sont sur le même fil.

+0

func1 obtient certainement ce verrou, parce que je le traverse dans le débogueur. La classe est en fait un singleton (je sais, je sais ...), donc je sais qu'il n'y a qu'une instance de la classe. Je ne comprends pas ce qui se passe ... – Steve

+0

@Steve. C'est ce que j'ai dit. Func1 peut obtenir le verrou, car il est appelé par Func2, qui a le verrou. –

+0

désolé, j'ai lu cela totalement faux. Merci pour l'aide. – Steve

1

.NET Les objets Monitor (dont les verrous sont utilisés) sont récursifs, de sorte qu'un thread qui détient le verrou peut y entrer à nouveau librement.

(Toutes les constructions de verrouillage sont récursives et arguments peuvent être contre le soutien récursive.)

+0

Ca a du sens, mais je ne le savais pas ... – Spence

3

La déclaration lock (encapsulant la classe Monitor) prend en charge re-entrée (récursion) dans un fil, à savoir que vous pouvez imbriquer les appels, qui utilisent le même moniteur.

Autres Approches de verrouillage:

  • Monitor - récursivité est supportée
  • ReaderWriterLock - récursion est prise en charge, mais lente
  • ReaderWriterLockSlim - récursion est pris en charge, mais découragée
  • EventHandle (ManualResetEvent, AutoResetEvent, Mutex, Semaphore) - récursivité non prise en charge