调用ResetEvent()时是否需要互斥或锁定?

时间:2012-04-09 16:16:49

标签: c++ windows multithreading

我继承了这样的代码:

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

SetEvent()

相同

在这种情况下,这些互斥锁是否必要 - 这些调用是自己行动还是我可以逃脱锁定?这个函数已经有了一些我早先生成的值的inc / decs,现在只是这些事件都在锁中,所以如果可能的话,摆脱它们将是一个很大的胜利。

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

警告程序员!

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

考虑以下代码:

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

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

在事件传递已发出信号后,工作人员可以通过racy interleaving重置事件,这会导致工作人员在等待时挂起。要在这种情况下正确使用手动重置事件,您需要获取重置事件周围的锁定,并通过重置事件来原子检查队列状态。

自动重置事件让你以原子方式唤醒并重置事件,避免这种竞争(如果你在工作进入时已经排空了队列,你可能会多醒一次,但你不会错过任何一次醒来)。

答案 2 :(得分:1)

事件是原子的,因此不需要在SetEventResetEvent周围使用互斥锁,除非还有其他内容,而且必须完成这两项操作原子地(例如,如果你设置一个事件并重置另一个事件)。