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