SemaphoreSlim的超时是否会失败?

Roy*_*mir 10 c# multithreading semaphore

信号量的真正力量是:

限制可以同时访问资源或资源池的线程数

这是明白的.

但是我从来没有机会玩过度Wait接受超时整数的重载,但是 - 这似乎允许多个线程进入临界区,尽管我已经明确设置信号量不允许一次允许多个线程:

private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);

private void Main()
{
    Task.Run(() => DelayAndIncrementAsync());
    Task.Run(() => DelayAndIncrementAsync());
}

private void DelayAndIncrementAsync()
{
    _mutex.Wait(2000);

    try
    {
        Console.WriteLine(0);
        Thread.Sleep(TimeSpan.FromSeconds(5));
        Console.WriteLine(1);
    }
    finally
    {
        _mutex.Release();
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

第一个线程进入互斥区域,打印"0"等待5秒,同时2秒后另一个线程进入临界区?

它不是在击败信号量的整个目的吗?

我将使用此超时的真实生活场景是什么,特别是当基本规则是 -

" 信号量 =限制可以同时访问资源或资源池的线程数

Spe*_*nce 15

您需要检查等待的返回值.基于超时的等待将尝试2秒钟来获取互斥锁然后返回.您需要检查返回值是否为真(即您是否具有互斥锁).

编辑:还要记住,如果信号量可用,则基于超时的等待将立即返回,因此您无法通过此技术阻止代码中的无限循环.

private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
void Main()
{

    Task.Run(()=>DelayAndIncrementAsync());
    Task.Run(()=>DelayAndIncrementAsync());
}
public   void  DelayAndIncrementAsync()
{
    if (_mutex.Wait(2000))
    {
        try
        {
            Console.WriteLine(0);
            Thread.Sleep(TimeSpan.FromSeconds(5));
            Console.WriteLine(1);
        }    
        finally
        {
            _mutex.Release();
        }
    } else {
        //oh noes I don't have the mutex
    }
}
Run Code Online (Sandbox Code Playgroud)


Rot*_*tem 5

您的误解是存在隐含的"互斥区域",而您未定义该区域.

Wait您正在使用的重载返回一个布尔值,该值告诉您是否成功输入了互斥锁.

您在示例中所做的是进入关键区域,无论线程是否已获取互斥锁,从而使其成为冗余.

通常,您希望在任何想要尝试输入互斥锁的情况下使用此重载,但如果当前无法在指定的时间内获取互斥锁,则还需要使用回退策略.