Reentrante bloqueia em c #

O seguinte código resultará em um deadlock usando C # no .NET?

class MyClass { private object lockObj = new object(); public void Foo() { lock(lockObj) { Bar(); } } public void Bar() { lock(lockObj) { // Do something } } } 

Não, desde que você esteja bloqueando o mesmo object. O código recursivo efetivamente já possui o bloqueio e assim pode continuar sem impedimentos.

lock(object) {...} é uma abreviação para usar a class Monitor . Como Marc aponta , o Monitor permite a reinput , então tentativas repetidas de travar um object no qual o segmento atual já tem um bloqueio funcionarão bem.

Se você começar a bloquear objects diferentes , é nesse momento que precisa ser cuidadoso. Preste atenção especial a:

  • Sempre adquirir bloqueios em um determinado número de objects na mesma seqüência.
  • Sempre solte os bloqueios na sequência inversa de acordo com a forma como você os adquire.

Se você quebrar alguma dessas regras, você está praticamente garantido em ter problemas de deadlock em algum momento .

Aqui está uma boa página da Web descrevendo a synchronization de threads no .NET: http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/

Além disso, bloqueie o menor número possível de objects de cada vez. Considere a possibilidade de aplicar bloqueios de granulação grossa sempre que possível. A ideia é que, se você puder escrever seu código de modo que exista um gráfico de object e possa adquirir bloqueios na raiz desse gráfico de object, faça isso. Isso significa que você tem um bloqueio nesse object raiz e, portanto, não precisa se preocupar tanto com a sequência na qual você adquire / libera bloqueios.

(Uma outra nota, seu exemplo não é tecnicamente recursivo. Para ser recursivo, Bar() teria que se chamar, normalmente como parte de uma iteração.)

Bem, o Monitor permite a reinput, então você não pode se fechar … então não: não deveria

Se um encadeamento já estiver segurando um bloqueio, ele não se bloqueará. A estrutura .Net garante isso. Você só precisa certificar-se de que os dois threads não tentam obter os mesmos dois bloqueios fora de seqüência, seja qual for o caminho do código.

O mesmo segmento pode adquirir o mesmo bloqueio várias vezes, mas você deve certificar-se de liberar o bloqueio o mesmo número de vezes que você o obtém. Naturalmente, desde que você esteja usando a palavra-chave “lock” para isso, isso acontece automaticamente.

Não, esse código não terá bloqueios mortos. Se você realmente quer criar deadlock, o mais simples requer pelo menos 2 resources. Considere o cenário do cão e do osso. 1. Um cão tem controle total sobre 1 osso, então qualquer outro cão tem que esperar. 2. 2 cães com 2 ossos são mínimos necessários para criar um impasse quando eles travam seus ossos respectivamente e buscam outros ossos também.

.. e assim por diante n cães e m ossos e causar deadlocks mais sofisticados.