Le code suivant entraînera-t-il un blocage en utilisant C # sur .NET?
class MyClass
{
private object lockObj = new object();
public void Foo()
{
lock(lockObj)
{
Bar();
}
}
public void Bar()
{
lock(lockObj)
{
// Do something
}
}
}
Non, pas tant que vous verrouillez le même objet. Le code récursif possède déjà le verrou et peut donc continuer sans entrave.
lock(object) {...}
est un raccourci pour utiliser la classe Monitor . Comme Marc souligne , Monitor
permet ré-entrée, donc des tentatives répétées de verrouiller un objet sur lequel le thread actuel a déjà un verrou fonctionnera très bien.
Si vous commencez à verrouiller des objets différents, c'est là que vous devez faire attention. Portez une attention particulière à:
Si vous enfreignez l'une de ces règles, vous avez à peu près la garantie d'obtenir des problèmes de blocage à un moment donné.
Voici une bonne page Web décrivant la synchronisation des threads dans .NET: http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/
En outre, verrouillez le moins d'objets à la fois possible. Envisagez d'appliquer verrous à gros grains dans la mesure du possible. L'idée étant que si vous pouvez écrire votre code de sorte qu'il existe un graphe d'objet et que vous puissiez acquérir des verrous à la racine de ce graphe d'objet, faites-le. Cela signifie que vous avez un verrou sur cet objet racine et que vous n'avez donc pas à vous soucier autant de la séquence dans laquelle vous acquérez/libérez les verrous.
(Une autre remarque, votre exemple n'est pas techniquement récursif. Pour qu'il soit récursif, Bar()
devrait s'appeler, généralement dans le cadre d'une itération.)
Eh bien, Monitor
permet la rentrée, donc vous ne pouvez pas vous bloquer vous-même ... donc non: cela ne devrait pas faire
Si un thread détient déjà un verrou, il ne se bloquera pas. Le framework .Net le garantit. Vous devez seulement vous assurer que deux threads n'essaient pas d'acquérir les deux mêmes verrous hors séquence par les chemins de code.
Le même thread peut acquérir le même verrou plusieurs fois, mais vous devez vous assurer de libérer le verrou le même nombre de fois que vous l'avez acquis. Bien sûr, tant que vous utilisez le mot clé "lock" pour cela, cela se produit automatiquement.
Non, ce code n'aura pas de verrous morts. Si vous voulez vraiment créer une impasse, la plus simple nécessite au moins 2 ressources. Considérez le scénario du chien et des os. 1. Un chien a le contrôle total sur 1 os, donc tout autre chien doit attendre. 2. 2 chiens avec 2 os sont nécessaires pour créer une impasse lorsqu'ils verrouillent leurs os respectivement et cherchent d'autres os aussi.
.. ainsi de suite et ainsi de suite n chiens et m os et provoquer des blocages plus sophistiqués.