如何实现下面的线程同步?

How to implement the following thread synchronization?

我有一个名为 Wait() 的方法,它是一个执行长 运行 的作业。它是同步的(它阻塞线程直到操作完成)

我想编写一个 Foo() 方法来实现以下逻辑:

The first thread who call Foo() method should call Wait() If another thread call Foo() after Wait() method has already been called once (and don't returned yet), it should wait/block until initial Wait() call is done.

我写了下面的代码,但我不确定它是否是线程安全的。也许有更好的方法。 我也尝试使用 Monitor.Pulse()/Monitor.Wait() 来实现逻辑,但没有成功。

void Foo()
{
    if (Monitor.TryEnter(mylock))
    {
        try
        {
            Wait();
        }
        finally
        {
            Monitor.Exit(mylock);
        }
    }
    else
    {
        lock(mylock) {}
    }
}

使用共享整数表示生成,使用共享布尔值表示线程是否在 Wait 中被阻塞。

布尔值跟踪另一个线程是否要调用等待。如果它是 true,那么我们只需要等待(释放监视器)直到另一个线程 returns 结束等待。我们知道会发生这种情况,因为它会增加共享整数。如果是false,那我们就要调用wait函数了。为了让其他线程(如果有的话)知道等待returns,我们增加共享整数并脉冲它们。

逻辑如下:

  1. 锁定监视器。
  2. 检查共享布尔值,如果是true,转到第12步。
  3. 将布尔值设置为 true
  4. 解锁显示器。
  5. 调用特殊的Wait函数。
  6. 锁定监视器。
  7. 增加共享整数
  8. 将共享布尔值设置为 false
  9. 在显示器上调用PulseAll
  10. 解锁显示器。
  11. Return.
  12. 将共享整数复制到私有整数中。
  13. 在监视器上调用 Wait
  14. 如果共享整数等于私有整数,转到步骤2。
  15. 解锁显示器。
  16. Return.

这可以通过信号量轻松完成,您只需等待超时为 0,如果等待失败,您将转到 else 块,等待它发出信号。

SemaphoreSlim _semaphore = ...

void Foo()
{

    try
    {
        if (_semaphore.Wait(0))
        {
            Wait();
        }
        else
        {
            _semaphore.Wait()
        }
    }
    finally
    {
        _semaphore.Release();
    }
}