https://blog.csdn.net/weixin_44228698/article/details/108672903
C#中的死锁和解决方案
- 在多任务系统下,当一个或多个进程等待系统资源,而资源又被进程本身或其它进程占用时,就形成了死锁。总的来说,就是两个线程,都需要获取对方锁占有的锁,才能够接着往下执行,但是这两个线程互不相让,你等我先释放,我也等你先释放,但谁都不肯先放,就一直在这僵持住了。
- 死锁的演示
static void Main(string[] args)
{
Task.Run(()=> Method1());
Task.Run(() => Method2());
Console.Read();
}
static void Method1()
{
lock (obj1)
{
Console.WriteLine("开始执行方法一");
Thread.Sleep(1000);
lock (obj2)
{
Console.WriteLine("方法一执行完毕");
}
}
}
static void Method2()
{
lock (obj2)
{
Console.WriteLine("开始执行方法二");
Thread.Sleep(1000);
lock (obj1)
{
Console.WriteLine("方法二执行完毕");
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
结果如下,这两个方法永远都不会执行完毕
3.那么,死锁应该怎么样解决呢?
- 首先,应该尽量避免大量嵌套的锁的使用,这也是预防为主,当然也有信号量也可能会造成死锁,这样的话只能靠程序员自身注意去避免了。
- 如果需要使用嵌套锁,可以使用锁的超时机制来避免对资源的长时间占用,演示如下:
private static readonly object obj1 = new object();
private static readonly object obj2 = new object();
static void Main(string[] args)
{
Task.Run(()=> Method1());
Task.Run(() => Method2());
Console.Read();
}
static void Method1()
{
try
{
if (Monitor.TryEnter(obj1, 5000))
{
Console.WriteLine("开始执行方法一");
Thread.Sleep(1000);
bool locked = false;
try
{
Monitor.TryEnter(obj2, 5000, ref locked);
Console.WriteLine("方法一执行完毕");
}
finally
{
if (locked)
{
Monitor.Exit(obj2);
}
}
}
}
finally
{
Monitor.Exit(obj1);
}
}
static void Method2()
{
try
{
if (Monitor.TryEnter(obj2, 5000))
{
Console.WriteLine("开始执行方法二");
Thread.Sleep(1000);
bool locked=false;
try
{
Monitor.TryEnter(obj1, 5000,ref locked);
Console.WriteLine("方法二执行完毕");
}
finally
{
if (locked)
{
Monitor.Exit(obj1);
}
}
}
}
finally
{
Monitor.Exit(obj2);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
这样,即使在两个线程都在互相等待资源的情况下,利用超时机制,依然能够使他们放弃当前锁,保证解决死锁问题。