我可以在此ManualResetEvent中使用锁来确保线程安全吗? [英] Can I use a lock with this ManualResetEvent to ensure thread safety?

查看:32
本文介绍了我可以在此ManualResetEvent中使用锁来确保线程安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个用于操作计数的函数,以及一个以固定间隔触发的OnTimer函数。

Say I have two functions that manipulate a count, and an OnTimer function that fires at a regular interval.

void IncrementCount()
{
    _myCount++;
}

void OverwriteCount(int newValue)
{
    _myCount = newValue;
}

void OnTimer()
{
    Console.WriteLine(_myCount);
}

我的愿望是,如果/当调用OverwriteCount时,IncrementCount不能为

My desire is that if/when OverwriteCount is called, IncrementCount can't be executed until the timer function executes.

我解决此问题的最初想法是使用ManualResetEvent来帮助同步行为:

My initial thought to resolve this was to use a ManualResetEvent to help synchronize behaviors:

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。

My concern is a degenerate, multi-threaded scenario where thread A gets past the mre.Wait() in IncrementCount() but hasn't actually incremented _myCount yet. Thread B then calls mre.Reset() and overwrites _myCount. Thread A then gets a turn and increments _myCount.

我可以通过在IncrementCount()和OverwriteCount()内添加锁以确保只有一个线程可以修改_myCount来解决此问题一次?如果我在握住锁的同时等待复位事件而陷入僵局,会不会招致死锁?

Could I solve this by also adding a lock inside IncrementCount() and OverwriteCount() to ensure only one thread can modify _myCount at a time? Do I risk deadlock if I get stuck waiting on the reset event while holding the lock?

推荐答案

如果我了解您,那么可以如果您选择合适的锁定方式,它将可以正常工作。可能有更细粒度的方法,但是到目前为止,我仍然没有发现任何

If i understand you, then yes it would work if you chose what to lock appropriately. There is probably a more granular way to do this, but as of now i see nothing wrong with this

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
}

这篇关于我可以在此ManualResetEvent中使用锁来确保线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆