假设我有两个用于操作计数的函数,以及一个以固定间隔触发的OnTimer函数。
void IncrementCount()
{
_myCount++;
}
void OverwriteCount(int newValue)
{
_myCount = newValue;
}
void OnTimer()
{
Console.WriteLine(_myCount);
}
我的愿望是,如果/当调用OverwriteCount时,在执行计时器函数之前无法执行IncrementCount。
我解决此问题的最初想法是使用ManualResetEvent来帮助同步行为:
private static ManualResetEventSlim mre = new ManualResetEventSlim(initialState: true);
void IncrementCount()
{
mre.Wait(-1); // can't increment until the event is signaled
_myCount++;
}
void OverwriteCount(int newValue)
{
mre.Reset(); // unsignal the event, blocking threads
_myCount = newValue;
}
void OnTimer()
{
Console.WriteLine(_myCount);
mre.Set(); // signal the event
}
我关心的是一个退化的多线程方案,其中线程A超过了IncrementCount()中的mre.Wait(),但实际上尚未增加_myCount。然后,线程B调用mre.Reset()并覆盖_myCount。然后,线程A转弯并增加_myCount。
我是否可以通过在IncrementCount()和OverwriteCount()中添加锁来解决这个问题,以确保一次只能有一个线程修改_myCount?如果我在握住锁的同时等待复位事件而陷入僵局,会冒险吗?
答案 0 :(得分:1)
如果我了解您,那么可以,只要您选择适当的锁定方式就可以。可能有更细粒度的方法可以做到这一点,但是到目前为止,我没有发现任何错误
void IncrementCount()
{
mre.Wait();
// lets not cause a race, lock until OverwriteCount is finished
lock (_sync)
{
_myCount++;
}
}
void OverwriteCount(int newValue)
{
// lock this so we can assure the count is updated
lock (_sync)
{
mre.Reset(); // unsignal the event, blocking threads
_myCount = newValue;
}
}
void OnTimer()
{
Console.WriteLine(_myCount);
mre.Set(); // signal the event
}