这段代码会导致死锁吗?
Can this code cause a dead lock ?
using System;
using System.Threading;
namespace Threading
{
class Program
{
static void Main(string[] args)
{
Semaphore even = new Semaphore(1, 1);
Semaphore odd = new Semaphore(1, 1);
Thread evenThread = new Thread(() =>
{
for (int i = 1; i <= 100; i++)
{
even.WaitOne();
if(i % 2 == 0)
{
Console.WriteLine(i);
}
odd.Release();
}
});
Thread oddThread = new Thread(() =>
{
for(int i = 1; i <=100; i++)
{
odd.WaitOne();
if(i%2 != 0)
{
Console.WriteLine(i);
}
even.Release();
}
});
oddThread.Start();
evenThread.Start();
}
}
}
所以我编写了这段代码,其中一个线程生成奇数,另一个线程生成偶数。
使用 Semaphores
我已经确保他们在订单中打印数字并且效果很好。
但我想到了一种特殊情况,例如,每个线程都在等待另一个线程释放其信号量。那么是否会出现两个线程都在等待并且没有线程取得任何进展并且出现死锁情况的情况?
要发生死锁,两个或多个线程必须尝试获取两个或多个资源,但以不同的顺序进行。参见例如Deadlock and Would you explain lock ordering?.
您的代码不涉及每个线程超过一个锁†,因此没有死锁能力。
它有能力抛出异常。如 中所述,理论上有可能其中一个线程比另一个线程提前足够远,以至于它试图释放尚未占用的信号量锁。例如,如果 evenThread
在第一次调用 even.WaitOne()
之前被抢占(或者根本没有安排启动 运行ning),但是 oddThread
到达运行,然后oddThread
可以获取odd
信号量,处理if
语句,然后尝试在evenThread
之前调用even.Release()
有机会获得那个信号量。
这将导致 SemaphoreFullException
被调用 Release()
抛出。
这在单CPU 系统上更有可能,现在很难找到。 :) 但理论上任何 CPU 配置都是可行的。
† 实际上,Console.WriteLine()
调用中有一个隐式锁,它在设计上是线程安全的。但从您的代码的角度来看,这是一个原子操作。您的代码不可能获取该锁然后等待另一个锁。所以它与你的具体问题没有任何关系。
using System;
using System.Threading;
namespace Threading
{
class Program
{
static void Main(string[] args)
{
Semaphore even = new Semaphore(1, 1);
Semaphore odd = new Semaphore(1, 1);
Thread evenThread = new Thread(() =>
{
for (int i = 1; i <= 100; i++)
{
even.WaitOne();
if(i % 2 == 0)
{
Console.WriteLine(i);
}
odd.Release();
}
});
Thread oddThread = new Thread(() =>
{
for(int i = 1; i <=100; i++)
{
odd.WaitOne();
if(i%2 != 0)
{
Console.WriteLine(i);
}
even.Release();
}
});
oddThread.Start();
evenThread.Start();
}
}
}
所以我编写了这段代码,其中一个线程生成奇数,另一个线程生成偶数。
使用 Semaphores
我已经确保他们在订单中打印数字并且效果很好。
但我想到了一种特殊情况,例如,每个线程都在等待另一个线程释放其信号量。那么是否会出现两个线程都在等待并且没有线程取得任何进展并且出现死锁情况的情况?
要发生死锁,两个或多个线程必须尝试获取两个或多个资源,但以不同的顺序进行。参见例如Deadlock and Would you explain lock ordering?.
您的代码不涉及每个线程超过一个锁†,因此没有死锁能力。
它有能力抛出异常。如 evenThread
在第一次调用 even.WaitOne()
之前被抢占(或者根本没有安排启动 运行ning),但是 oddThread
到达运行,然后oddThread
可以获取odd
信号量,处理if
语句,然后尝试在evenThread
之前调用even.Release()
有机会获得那个信号量。
这将导致 SemaphoreFullException
被调用 Release()
抛出。
这在单CPU 系统上更有可能,现在很难找到。 :) 但理论上任何 CPU 配置都是可行的。
† 实际上,Console.WriteLine()
调用中有一个隐式锁,它在设计上是线程安全的。但从您的代码的角度来看,这是一个原子操作。您的代码不可能获取该锁然后等待另一个锁。所以它与你的具体问题没有任何关系。