Je me demande si cette construction va provoquer une erreur:
lock(sync)
{
// something
lock(sync)
{
//something
lock(sync)
{
//something
}
}
}
J'ai exécuté ce code, et cela semble correct, mais peut-être que dans certaines circonstances une erreur peut être générée?
lock
est un wrapper pour Monitor.Enter
et Monitor.Exit
:
Le mot clé
lock
appelleEnter
au début du bloc etExit
à la fin du bloc. D'après la documentation du premier:
D'après la documentation de Monitor.Enter
:
Il est légal que le même thread appelle
Enter
plus d'une fois sans le bloquer; cependant, un nombre égal d'appelsExit
doit être appelé avant que d'autres threads en attente sur l'objet ne se débloquent.
Étant donné que les appels à Enter
et Exit
sont associés, votre modèle de code a un comportement bien défini.
Notez cependant que lock
n'est pas garanti d'être une construction sans exception:
Un
ThreadInterruptedException
est levé siInterrupt
interrompt un thread qui attend d'entrer une instructionlock
.
Pour expliquer pourquoi il s'agit d'un comportement bien défini et qui n'échouera jamais:
Mis à part: Cette réponse contient de meilleurs détails sur le fonctionnement réel des verrous
Le verrou se produit au niveau Thread
, donc l'appeler une deuxième fois sur le même thread sera redondant. Je pense qu'il n'y aurait pas de pénalité de performance (bien que cela dépende de la façon dont les composants internes de .Net sont écrits, je ne peux donc pas garantir cela)
Plusieurs fois, vous auriez une fonction publique qui appelle une autre fonction publique de votre classe, qui ont toutes deux besoin du verrou lorsqu'elles sont utilisées séparément. Si cela n'était pas autorisé, les éléments suivants échoueraient:
private Dictionary<string, int> database = new Dictionary<string, int>();
private object databaseLock = new object();
public void AddOrUpdate(string item)
{
lock (databaseLock)
{
if (Exists(item))
database.Add(item, 1);
else
++database[item];
}
}
public bool Exists(string item)
{
lock (databaseLock)
{
//... Maybe some pre-processing of the key or item...
return database.ContainsKey(item);
}
}