C# 我可以将锁与此ManualResetEvent一起使用以确保螺纹安全吗?

C# 我可以将锁与此ManualResetEvent一起使用以确保螺纹安全吗?,c#,.net,concurrency,C#,.net,Concurrency,假设我有两个操作计数的函数和一个按固定间隔触发的OnTimer函数 void IncrementCount() { _myCount++; } void OverwriteCount(int newValue) { _myCount = newValue; } void OnTimer() { Console.WriteLine(_myCount); } 我的愿望是,如果调用OverwriteCount,则在计时器函数执行之前无法执行IncrementCount 我

假设我有两个操作计数的函数和一个按固定间隔触发的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?如果我在持有锁的同时等待重置事件,是否会有死锁的风险?

如果我理解您的意思,那么如果您选择了适当的锁定方式,则会成功。也许有一种更精细的方法可以做到这一点,但到目前为止,我看不出这有什么错

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
}

如果我想确保_myCount在OnTimer中不能更改,那么Console.WriteLine和mre.Set()周围的锁(_sync)是否正常?@Craig这是正确的,不会死锁。我在这个逻辑中发现了一个竞争条件。我已经打开了一个轨道