【问题标题】:Can I use a lock with this ManualResetEvent to ensure thread safety?我可以在此 ManualResetEvent 中使用锁来确保线程安全吗?
【发布时间】:2019-06-13 01:28:22
【问题描述】:

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

【问题讨论】:

    标签: c# .net concurrency


    【解决方案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
    }
    

    【讨论】:

    • 如果我想确保 _myCount 在 OnTimer 中不会发生变化,Console.WriteLine 和 mre.Set() 周围的 lock(_sync) 是否正常?
    • @Craig 那是正确的,不会死锁
    • 我在这个逻辑中发现了一个竞争条件。我打开了separate question 来跟踪
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 2010-09-25
    • 2022-01-10
    • 1970-01-01
    • 2021-03-21
    相关资源
    最近更新 更多