这段代码可以导致死锁吗?

时间:2017-04-23 16:15:29

标签: c# deadlock

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我确保他们按顺序打印数字并且效果很好。

但我有一个特殊的情况,例如每个线程等待,直到另一个线程释放其信号量。那么是否存在两个线程都在等待并且没有线程正在进行任何进展并且存在死锁情况的情况?

1 个答案:

答案 0 :(得分:1)

要发生死锁,两个或多个线程必须尝试获取两个或多个资源,但是以不同的顺序执行。参见例如DeadlockWould you explain lock ordering?

您的代码每个线程不涉及多个锁,因此无法解锁死锁。

能够抛出异常。正如this comment中所指出的,理论上其中一个线程可以在另一个线程之前足够远,它试图释放尚未被采用的信号量锁定。例如,如果evenThread在第一次调用even.WaitOne()之前被抢先(或者根本没有被安排开始运行),但是oddThread会运行,那么oddThread可以获取odd信号量,处理if语句,然后在even.Release()有机会获得该信号量之前尝试调用evenThread。< / p>

这会导致SemaphoreFullException的调用引发Release()

这在单CPU系统上更有可能发生,这些日子很难找到。 :)但从理论上讲,它仍然适用于任何CPU配置。


†实际上,Console.WriteLine()调用中存在隐式锁定,这在设计上是线程安全的。但是从你的代码的角度来看,这是一个原子操作。您的代码无法获取该锁定,然后等待另一个锁定。所以它与您的具体问题没有任何关系。