Win32事件对象递归互斥?

时间:2012-04-23 07:50:17

标签: windows multithreading locking mutex deadlock

我搜索了MSDN,Mutex可以被锁定两次,但是在同一个线程中没有任何关于递归的单词两次获取相同的事件对象。

我们可以在同一个线程中两次锁定win32事件吗?

编辑:锁定事件的含义是什么?在这里我假设事件是自动重置。

  1. 锁定:从WaitForXXX中唤醒一个线程(例如,WaitForSingleObject)
  2. Un-Lock:一个线程正在调用SetEvent或PluseEvent。

2 个答案:

答案 0 :(得分:3)

互斥体与事件根本不同。虽然互斥锁用于提供MUTual EXclusion,因此一次只有一个线程可以访问资源,而事件只是一种通知机制。自动重置事件提供单次唤醒通知,而手动重置事件提供多次唤醒通知。

如果发出自动重置事件的信号,则只有一个线程会收到该信号,该线程只接收一次;任何其他线程---或来自同一线程的该事件的等待函数的任何其他调用---将等到第二次调用SetEvent

如果您发出手动重置事件的信号,那么它会一直保持信号状态,直到您重置它为止,因此可以唤醒多个线程,并且从同一线程多次调用该事件的等待函数将成功,直到某些线程调用{{1} }。

事件没有一个“所有者”:只是因为线程A上次被另一个设置事件的线程从等待函数的调用中唤醒,没有任何东西阻止它再次等待,没有任何东西指定如果两个节点都在同一个自动重置事件上等待,则是否会唤醒线程A或B.也没有什么需要任何特定线程来调用ResetEvent:系统中的任何线程都可以这样做,无论该线程是否曾为该事件调用等待函数。实际上,一个常见的用例有一个线程调用SetEvent,一个或多个其他线程在等待。

所以:是的,您可以等待来自等待该事件的线程的事件,但这不是锁定,其他线程也可能等待事件,并且如果事件发出信号也可能唤醒。

已修改问题的更新:

您可以使用事件来提供锁定,但这不是固有语义的一部分。您可以使用相同的自动重置事件句柄连续两次调用SetEvent。就Windows而言,这不是一个错误:您只需确保其他一些线程或线程调用WaitForSingleObject两次,以便等待线程从第一次调用唤醒SetEvent在第二次调用WaitForSingleObject之前,为了避免“丢失”唤醒:SetEvent不计算呼叫,它只是设置标志。

另外:不要使用SetEvent。即使当前正在等待线程,它也不能保证线程会被唤醒。

答案 1 :(得分:2)

我同意Anthony Williams的观点。

我想补充的一点是,很多人(不仅仅是你)不太了解互斥锁和自动重置事件之间的区别。它们实际上表现相似,可能(从技术角度来看)用于资源锁定。

它们之间的主要区别在于互斥锁“知道”哪个线程拥有它。也就是说,当WaitForSingleObject(或类似)获取互斥锁时 - 它会自动“分配”到调用线程。这有两个后果:

  1. 可以通过相同的线程递归地获取互斥锁。当然,这不适用于自动重置事件。
  2. 如果拥有互斥锁的线程退出 - 互斥锁会自动“释放”。相应的WaitXXXX函数将返回WAIT_ABANDONED
  3. 事件OTOH可能被视为信号量的特殊情况。自动重置事件相当于由(最多)1和手动重置事件收取的信号量 - 相当于无限充电的信号量。