我试图为死锁创建一个示例。我尝试了以下代码。但它并没有造成僵局,而是像魅力一样。帮助我理解为什么它没有造成死锁。这段代码有什么变化会造成死锁?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ReferenceTypes
{
class DeadLockExample
{
static int a;
static int b;
public static void Main(string[] args)
{
DeadLockExample.a = 20;
DeadLockExample.b = 30;
DeadLockExample d = new DeadLockExample();
Thread tA = new Thread(new ThreadStart(d.MethodA));
Thread tB = new Thread(new ThreadStart(d.MethodB));
tA.Start();
tB.Start();
Console.ReadLine();
}
private void MethodA()
{
lock (this)
{
Console.WriteLine(a);
Thread.Sleep(1000);
Console.WriteLine(b);
}
}
private void MethodB()
{
lock (this)
{
Console.WriteLine(b);
Thread.Sleep(1000);
Console.WriteLine(a);
}
}
}
}
答案 0 :(得分:11)
正如其他人所说的那样,两个锁以不同的顺序获得,所以每个人都在等待另一个。我还更改了其中一个Sleep长度,以确保发生死锁的可能性很高。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ReferenceTypes
{
class DeadLockExample
{
static int a;
static int b;
static object lockedObjA = new object();
static object lockedObjB = new object();
public static void Main(string[] args)
{
DeadLockExample.a = 20;
DeadLockExample.b = 30;
DeadLockExample d = new DeadLockExample();
Thread tA = new Thread(new ThreadStart(d.MethodA));
Thread tB = new Thread(new ThreadStart(d.MethodB));
tA.Start();
tB.Start();
Console.ReadLine();
}
private void MethodA()
{
lock (DeadLockExample.lockedObjA)
{
Console.WriteLine(a);
Thread.Sleep(1200);
lock (DeadLockExample.lockedObjB) {
Console.WriteLine(b);
}
}
}
private void MethodB()
{
lock (DeadLockExample.lockedObjB)
{
Console.WriteLine(b);
Thread.Sleep(1000);
lock (DeadLockExample.lockedObjA) {
Console.WriteLine(a);
}
}
}
}
}
答案 1 :(得分:3)
2个锁,2个线程。
线程A获取锁A,休眠然后尝试获取锁B.线程B获取锁B,休眠然后尝试获取锁A,等于死锁。
[线程A必须长时间休眠,以便线程B在线程A尝试获取之前获取锁定B]
答案 2 :(得分:1)
以下3种不同的方法可以导致死锁。这份清单并非详尽无遗。
从锁定部分调用阻止方法。
在这个示例中,线程A获取一个锁,然后立即调用阻塞方法,同时线程B尝试获取相同的锁,但是因为线程A正在等待线程B发出信号之前它被挂起释放锁。
public class Example
{
ManualResetEvent m_Event = new ManualResetEvent(false);
void ThreadA()
{
lock (this)
{
m_Event.WaitOne();
}
}
void ThreadB()
{
lock (this)
{
m_Event.Set();
}
}
}
无序获取两个锁。
这里不需要解释,因为这是一个众所周知的问题。
public class Example
{
private object m_LockObjectA = new object();
private object m_LockObjectB = new Object();
void ThreadA()
{
lock (m_LockObjectA) lock (m_LockObjectB) { }
}
void ThreadB()
{
lock (m_LockObjectB) lock (m_LockObjectA) { }
}
}
无锁死锁。
这是我最喜欢的死锁插图,因为不涉及锁定或阻塞方法。这个问题的微妙之处足以让那些熟悉线程的人感到困惑。这里的问题与缺乏记忆障碍有关。线程A等待线程B设置信号标志,同时线程B等待线程A重置它,而线程没有看到对方正在进行的更改,因为编译器,JIT和硬件可以自由优化以不直观的方式读取和写入标志。
public class Example
{
private bool m_Signal = false;
void ThreadA()
{
while (!m_Signal);
m_Signal = false;
}
void ThreadB()
{
m_Signal = true;
while (m_Signal);
}
}
答案 3 :(得分:0)
来自维基百科 -
死锁是两种情况 或者更多的竞争行为 等待对方完成,并且 从来没有。
您没有使用上面的代码满足此要求 - 线程A和线程B都没有等待彼此完成。