如何实现下面的线程同步?
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,我们增加共享整数并脉冲它们。
逻辑如下:
- 锁定监视器。
- 检查共享布尔值,如果是
true
,转到第12步。
- 将布尔值设置为
true
。
- 解锁显示器。
- 调用特殊的
Wait
函数。
- 锁定监视器。
- 增加共享整数
- 将共享布尔值设置为
false
。
- 在显示器上调用
PulseAll
- 解锁显示器。
- Return.
- 将共享整数复制到私有整数中。
- 在监视器上调用
Wait
。
- 如果共享整数等于私有整数,转到步骤2。
- 解锁显示器。
- Return.
这可以通过信号量轻松完成,您只需等待超时为 0,如果等待失败,您将转到 else 块,等待它发出信号。
SemaphoreSlim _semaphore = ...
void Foo()
{
try
{
if (_semaphore.Wait(0))
{
Wait();
}
else
{
_semaphore.Wait()
}
}
finally
{
_semaphore.Release();
}
}
我有一个名为 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 initialWait()
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,我们增加共享整数并脉冲它们。
逻辑如下:
- 锁定监视器。
- 检查共享布尔值,如果是
true
,转到第12步。 - 将布尔值设置为
true
。 - 解锁显示器。
- 调用特殊的
Wait
函数。 - 锁定监视器。
- 增加共享整数
- 将共享布尔值设置为
false
。 - 在显示器上调用
PulseAll
- 解锁显示器。
- Return.
- 将共享整数复制到私有整数中。
- 在监视器上调用
Wait
。 - 如果共享整数等于私有整数,转到步骤2。
- 解锁显示器。
- Return.
这可以通过信号量轻松完成,您只需等待超时为 0,如果等待失败,您将转到 else 块,等待它发出信号。
SemaphoreSlim _semaphore = ...
void Foo()
{
try
{
if (_semaphore.Wait(0))
{
Wait();
}
else
{
_semaphore.Wait()
}
}
finally
{
_semaphore.Release();
}
}