我继承了一些这样的代码:
m_mutex.Lock();
ResetEvent( m_hSyncObject );
m_mutex.Unlock();
相同的SetEvent()
在这种情况下,这些互斥锁是必需的吗?这些调用是否会表现自己,或者我可以摆脱锁吗?这个函数已经有一些我之前原子化的值 inc/decs,现在这些事件都在锁中,所以如果可能的话,摆脱它们将是一个巨大的胜利。
我继承了一些这样的代码:
m_mutex.Lock();
ResetEvent( m_hSyncObject );
m_mutex.Unlock();
相同的SetEvent()
在这种情况下,这些互斥锁是必需的吗?这些调用是否会表现自己,或者我可以摆脱锁吗?这个函数已经有一些我之前原子化的值 inc/decs,现在这些事件都在锁中,所以如果可能的话,摆脱它们将是一个巨大的胜利。
这个额外的互斥锁几乎肯定是不需要的。和函数本身可以安全地从多个线程ResetEvent
调用SetEvent
鉴于此代码确实存在,编写该代码的开发人员很可能不理解他们创建的线程语义。我会将任何取决于该逻辑的代码视为高度可疑的。从长远来看,它可能会为您节省一些时间来继续预先审核该代码以解决线程问题
警告程序员!
手动重置事件很难使用,并且可能需要您锁定设置和重置事件(自动重置事件可以更轻松地避免这些问题)。
考虑这段代码:
Worker() {
WaitForSingleObject(hEvent);
DoWork();
ResetEvent(hEvent);
}
EventThread() {
QueueWork();
SetEvent(hEvent);
}
在 EventThread 发出信号后,worker 可能会通过 racy interleaving 重置事件,这将导致 worker 在等待时挂起。要在这种情况下正确使用手动重置事件,您需要获取重置事件周围的锁,并通过重置事件原子地检查队列的状态。
自动重置事件让您自动唤醒并重置避免这场比赛的事件(如果您在工作进入时已经排空队列,您可能会额外唤醒一次,但您不会错过任何唤醒)。
Events are atomic, so there's no need to use a mutex around a SetEvent
or ResetEvent
, unless there's something else along with it and the two have to be done atomically (e.g., if you set one event and reset another).