我可以在此ManualResetEvent中使用锁来确保线程安全吗?

时间:2019-06-13 01:28:22

标签: c# .net concurrency

假设我有两个用于操作计数的函数,以及一个以固定间隔触发的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?如果我在握住锁的同时等待复位事件而陷入僵局,会冒险吗?

1 个答案:

答案 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
}