【问题标题】:Do I need to mutex or lock when calling ResetEvent()?调用 ResetEvent() 时是否需要互斥或锁定?
【发布时间】:2012-04-09 16:16:49
【问题描述】:

我继承了一些这样的代码:

m_mutex.Lock();
ResetEvent( m_hSyncObject );
m_mutex.Unlock();

SetEvent() 也一样

在这种情况下,这些互斥锁是必需的吗?这些调用是否会表现自己,或者我可以摆脱锁吗?这个函数已经有一些我之前原子化的值 inc/decs,现在只有这些事件在锁中,所以如果可能的话,摆脱它们将是一个巨大的胜利。

【问题讨论】:

  • 你不需要额外的互斥体

标签: c++ windows multithreading


【解决方案1】:

这个额外的互斥锁几乎肯定是不需要的。 ResetEventSetEvent 函数本身可以安全地从多个线程调用

鉴于此代码确实存在,编写该代码的开发人员很可能不了解他们创建的线程语义。我会将任何取决于该逻辑的代码视为高度可疑的。从长远来看,它可能会为您节省一些时间来继续预先审核该代码以解决线程问题

【讨论】:

  • 已经完成了。 Profiler 显示了大量对“快速”锁的调用。 Job System 严重滥用了他们。这些是我在锁定时不确定的最后两个功能。现在,按照您的建议,我正在浏览代码,确保其他所有内容都正常......
  • 'Profiler 显示了大量对“快速”锁的调用' - 天哪 :(( 我很同情。
【解决方案2】:

程序员注意!

手动重置事件很难使用,可能需要您锁定设置和重置事件(自动重置事件更容易避免这些问题)。

考虑这段代码:

Worker() {
    WaitForSingleObject(hEvent);
    DoWork();
    ResetEvent(hEvent);
}

EventThread() {
    QueueWork();
    SetEvent(hEvent);
}

在 EventThread 发出信号之后,worker 可能会通过 racy interleaving 重置事件,这将导致 worker 在等待时挂起。在这种情况下,要正确使用手动重置事件,您需要获取重置事件周围的锁,并通过重置事件自动检查队列的状态。

自动重置事件让您自动唤醒并重置事件以避免这场比赛(如果您在工作进入时已经排空队列,您可能会额外唤醒一次,但您不会错过任何唤醒)。

【讨论】:

    【解决方案3】:

    事件是原子的,所以没有必要在 SetEventResetEvent 周围使用互斥锁,除非还有其他东西,并且这两者必须以原子方式完成(例如,如果您设置一个事件并重置另一个事件)。

    【讨论】:

    • 不,不是那样的。设置和重置已经在单独的关键部分中,但我会检查以确保它们不应该被锁定在一起。不错的建议。
    猜你喜欢
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-31
    • 2010-09-12
    • 2011-09-06
    • 2012-03-25
    • 2019-09-17
    相关资源
    最近更新 更多