Пример тупика в .net?
Может ли кто-нибудь дать простой пример кода Deadlock в С#? И, пожалуйста, скажите простейший способ найти тупик в своем примере кода С#. (Может быть инструментом, который обнаружит мертвую блокировку в данном примере кода.)
ПРИМЕЧАНИЕ. У меня есть VS 2008
Ответы
Ответ 1
один общий способ - если у вас есть вложенные блокировки, которые не получены в том же порядке. Нить 1 могла бы получить блокировку A, а нить 2 могла бы получить блокировку B, и они были бы тупиковыми.
var a = new object();
var b = new object();
lock(a) {
lock(b) {
}
}
// other thread
lock (b) {
lock(a) {
}
}
редактирование: неблокирующий пример.. используя waithandles. Предположим, что у Сократа и Декарта есть стейки, и они оба, будучи воспитанными философами, нуждаются в вилке и ноже, чтобы есть. Тем не менее, у них есть только один комплект серебра, поэтому каждый может захватить одну посуду, а затем ждать навсегда, чтобы другой мог передать свою посуду.
См. Обеденная проблема философа
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();
}
Ответ 2
Это типичный код для создания тупика в коде С#.
Ознакомьтесь с этой статьей 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();
}
}
Ответ 3
Для кода примера взаимоблокировки попробуйте использовать lock(this)
в своем классе для имитации сценария взаимоблокировки. Оформить заказ этот пример.
После двух достойных статей для чтения обнаруживает тупик во время выполнения и обсуждает способы их устранения.
Ответ 4
Есть еще один способ добиться тупика в С#. Поскольку число потоков .NET 2.0 SP1 в пуле ограничено 250 (от 25 в предыдущей версии) на ядро.
Итак, технически вы можете запустить слишком много задач в пуле, которые ждут завершения для другой операции async (которая выполняется через пул потоков). Таким образом, задача в пуле не будет выпущена, и задача async не будет запущена, потому что нет доступных потоков.
Здесь вы можете найти пример и более точное объяснение:
Программирование пула потоков. Тупики
Ответ 5
Чтобы ответить на часть вашего вопроса об обнаружении тупика, я скорее сомневаюсь, что это вообще возможно. Это похоже на проблему с остановкой, вы не можете эффективно вычислить семантику. Один из способов преодолеть это - использовать сторожевой таймер, который будет периодически опросить каждый поток, если он еще жив, и дать ему определенный тайм-аут для ответа, если 2 потока не отвечают, вы можете предположить, что они либо заняты, либо они мертвы, заперта.