C# 多线程中的死锁
我试图为死锁创建一个示例。我尝试了以下代码。但它并没有造成僵局,反而发挥了魅力。帮助我理解为什么它没有造成死锁。此代码中的什么更改会导致死锁C# 多线程中的死锁,c#,multithreading,C#,Multithreading,我试图为死锁创建一个示例。我尝试了以下代码。但它并没有造成僵局,反而发挥了魅力。帮助我理解为什么它没有造成死锁。此代码中的什么更改会导致死锁 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ReferenceTypes { class DeadLockExample { s
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);
}
}
}
}
2个锁,2个螺纹
线程A获取锁A,休眠,然后尝试获取锁B。线程B获取锁B,休眠,然后尝试获取锁A,等于死锁
[线程A必须睡眠足够长的时间,以便线程B在线程A尝试获取锁B之前获取锁B]来自维基百科-
僵局是指两种情况
每一个或多个相互竞争的行动
等待另一个完成,然后
因此,两者都没有
上面的代码不能满足这一要求-线程a和线程B从来没有一点都在等待对方完成。正如其他人所说,两个锁以不同的顺序获得,因此每个锁都在等待对方。我还更改了其中一个睡眠长度,以确保死锁发生的高概率
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);
}
}
}
}
}
以下是导致死锁的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);
}
}
除了睡眠不能保证死锁的发生(只有同步才能做到这一点),这是一个很好的答案:)我很欣赏这个答案。谢谢。这是典型的死锁示例。实际上,大多数死锁看起来都与此完全相同,只是锁获取通常在堆栈跟踪中至少相隔8次调用,然后通过从您甚至没有意识到正在运行的线程上的计时器事件的回调进行路由。