首页 > 解决方案 > 为什么调用 Semaphore.WaitOne 会出现死锁?

问题描述

run()以下代码中的函数同时从其他线程调用。根据应用程序的一般设计,在任何时候,在任何行,都可能发生 ThreadAbortException,这是我无法更改的。

我有时会SemaphoreFullException在打电话时得到pool.Release()。我认为如果在调用“pool.WaitOne()”时发生线程中止异常,就会发生这种情况。在我的调试尝试中,发生 SemaphoreFullException 后,运行代码没有问题。在那个异常之后,pool.WaitOne()调用和其他事情就像预期的那样工作。

在我的本地调试会话期间,我无法遇到死锁情况。但是,在远程计算机中,我的代码出现了死锁。我使用远程调试器附加该进程,并看到执行被锁定在行上pool.WaitOne();

我无法弄清楚这将如何发生,以及我做错了什么。非常感谢任何帮助。

private static object poolLocker = new object();
private static Semaphore _pool;
private static Semaphore pool
{
    get
    {
       if (_pool == null)
           lock (poolLocker)
       if (_pool == null)
       {
           int count = myMaximumThreadCount;
           _pool = new Semaphore(count, count);
       }
       return _pool;
    }
}

private void run()
{
    try
    {
        pool.WaitOne();

        do_something_that_may_throw_exception();
    }
    finally
    {
        try
        {
            pool.Release();
        }
        catch (SemaphoreFullException) { }
    }
}

标签: c#deadlocksemaphore

解决方案


尝试将pool属性中信号量对象的初始化更改为:

private static Semaphore pool
{
    get
    {
       if (_pool == null)
           lock (poolLocker)
       if (_pool == null)
       {
           int count = myMaximumThreadCount;
           _pool = new Semaphore(0, count);
       }
       return _pool;
    }
}

此信号量的初始计数应设置为零。


推荐阅读