Образец тупика в .net? - PullRequest
11 голосов
/ 30 марта 2010

Кто-нибудь может дать простой пример кода Deadlock в c #? И, пожалуйста, расскажите самый простой способ найти тупик в вашем примере кода на C #. (Может быть инструментом, который обнаружит мертвую блокировку в данном примере кода.)

ПРИМЕЧАНИЕ: у меня VS 2008

Ответы [ 5 ]

18 голосов
/ 30 марта 2010

Один из распространенных способов - если у вас есть вложенные блокировки, которые не получены в том же порядке. Поток 1 может получить блокировку A, а поток 2 может получить блокировку B, и они заблокируются.

var a = new object();
var b = new object();

lock(a) {
   lock(b) {

   }
}

// other thread
lock (b) { 
  lock(a) {

  }
}

edit: неблокирующий пример .. с использованием ручек ожидания. Предположим, у Сократа и Декарта есть стейки, и они оба, будучи воспитанными философами, нуждаются в вилке и ноже, чтобы есть. Тем не менее, у них есть только один набор столового серебра, поэтому каждый может взять одну посуду и затем ждать вечно, пока другая сдаст свою посуду.

См. Обеденная философская проблема

WaitHandle fork = new AutoResetEvent(), knife = new AutoResetEvent();

while(Socrates.IsHungry) {
   fork.WaitOne();
   knife.WaitOne();
   Eat();
   fork.Set();
   knife.Set();
} 

// other thread
while(Descartes.IsHungry) {
   knife.WaitOne();
   fork.WaitOne();
   Eat();
   knife.Set();
   fork.Set();
} 
5 голосов
/ 03 июня 2010

Это типичный код для создания тупика в коде C #. Оформить заказ на эту статью MSDN: http://msdn.microsoft.com/en-us/magazine/cc188793.aspx

using System;

using System.Threading;


public class Simple {

    static object A = new object();

    static object B = new object();


    static void MethodA()
    {
        Console.WriteLine("Inside methodA");
        lock (A)
        {
            Console.WriteLine("MethodA: Inside LockA and Trying to enter LockB");
            Thread.Sleep(5000);           
            lock (B)
            {
                Console.WriteLine("MethodA: inside LockA and inside LockB");
                Thread.Sleep(5000);
            }
            Console.WriteLine("MethodA: inside LockA and outside LockB");
        }
        Console.WriteLine("MethodA: outside LockA and outside LockB");
    }

    static void MethodB()
    {
        Console.WriteLine("Inside methodB");
        lock (B)
        {
            Console.WriteLine("methodB: Inside LockB");
            Thread.Sleep(5000);
            lock (A)
            {
                Console.WriteLine("methodB: inside LockB and inside LockA");
                Thread.Sleep(5000);
            }
            Console.WriteLine("methodB: inside LockB and outside LockA");
        }
        Console.WriteLine("methodB: outside LockB and outside LockA");
    }

    public static void Main(String[] args)
    {

        Thread Thread1 = new Thread(MethodA);
        Thread Thread2 = new Thread(MethodB);
        Thread1.Start();
        Thread2.Start();
        Console.WriteLine("enter.....");
        Console.ReadLine();

    }
}
1 голос
/ 03 июня 2010

Чтобы ответить на часть вашего вопроса об обнаружении взаимоблокировки, я скорее сомневаюсь, что это вообще возможно. Это похоже на проблему остановки, вы не можете эффективно вычислить семантику. Один из способов преодолеть это - использовать сторожевой таймер, который периодически опрашивал бы каждый поток, если он еще жив, и давал ему определенное время для ответа. Если два потока не отвечают, вы можете предположить, что они либо заняты, либо не работают. заблокирован.

1 голос
/ 30 марта 2010

Есть еще один способ добиться тупика в C #. Начиная с версии .NET 2.0 SP1 количество потоков в пуле ограничено 250 (из 25 в предыдущей версии) на ядро.

Таким образом, технически вы можете запустить слишком много задач в пуле, ожидающих завершения для другой асинхронной операции (которая выполняется через пул потоков). Поэтому задача в пуле не будет освобождена, и асинхронная задача не запустится, поскольку нет доступных потоков.

Вы можете найти пример и более точное объяснение здесь: Программирование пула потоков. Тупики

1 голос
/ 30 марта 2010

В качестве примера кода взаимоблокировки попробуйте использовать lock(this) в своем классе для имитации сценария взаимоблокировки. Оформить заказ этот пример .

После двух достойных чтения статей обнаруживает тупик во время выполнения и обсуждает способы их устранения.

  1. Монитор тупика Стивена Туба.
  2. TimedLock Again от Иана Гриффитса.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...