首页 > 解决方案 > 为什么在使用信号量时这 4 个线程会被锁定?

问题描述

在一个可能有很多很多线程的系统中,我试图确保一次只实例化一个类的四个实例,并且可能在 5-60 秒后释放。实例在每个线程开始时创建,并在线程中的进程结束时销毁。

我还想防止一次只构建一个实例。所以我的逻辑是在对象实例化期间使用锁,但也用信号量包装整个线程逻辑。

private static readonly object padlock = new object();
private static readonly Semaphore mutablelock = new Semaphore(0, 4);

// called at the start of a long running thread
public static Object GetNewInstance()
{
    // semaphore used to prevent more than 4 objects from existing at any time
    mutablelock.WaitOne();

    // lock used to prevent more than one object being instantiated at a time
    lock (padlock)
    {
        var instance = new Object();
        return instance;
    }
}

// called at the end of a long running thread
public static void ReleaseInstance()
{
    mutablelock.Release();
}

该程序有四个线程(当使用调试停止点查看时)每个线程都停止在该mutablelock.WaitOne();行并且不再继续前进。

标签: c#multithreadinglockingsemaphorerace-condition

解决方案


您正在构建您Semaphore的所有条目都已保留的方式。Semaphore接受两个参数的构造函数有这样的说法:

如果initialCount小于maximumCount,则效果与当前线程已调用WaitOnemaximumCount减去initialCount)次相同。如果您不想为创建信号量的线程保留任何条目,请对maximumCountinitialCount使用相同的数字。

所以做这个改变:

private static readonly Semaphore mutablelock = new Semaphore(4, 4);

推荐阅读