我有 5 个线程(在多核系统上)同时等待:
- 要获取的互斥锁 M
- 要发出信号的事件 E
我正在使用WaitForMultipleObjectsEx(..., TRUE, INFINITE, TRUE)
,因为线程使用 APC。
请注意,APC不会以任何方式使用/触摸/更改/观察互斥锁或事件。
我正在使用 Visual Studio 和Process Hacker进行调试,我正在目睹一个奇怪的现象:
通常,应该运行的线程(称为线程 A)仍在等待这两个对象。
我说“应该运行”是因为:
- 我已经多次验证(包括通过 Process Hacker)E 确实处于信号状态
- 没有其他线程获得 M 的所有权。实际上,还有3 个其他线程也在等待获得 M。
然而,根据 Process Hacker(用于NtQueryMutant
检索计数)的说法,在这种情况下,M 的“计数”值低得离谱,例如 -618。
当然,我没有忘记调用ReleaseMutex
(是的,我也在检查返回值);事实上,一旦有人后来获得了互斥锁,Count 就会重新增加。
所以这引出了一个问题:如果其他 4 个线程中有 3 个正在休眠,那么最后一个线程(B)在做什么?
答案是 B 正在调用中执行 APC 。无论我在 Visual Studio 中“逐步”通过 B 多远(甚至一直备份),其他线程都不会唤醒。
只有在APC 完成执行后,才会唤醒任何线程!WaitForMultipleObjectsEx
RtlDispatchAPC
我觉得这很奇怪,WaitForMultipleObjectEx
文档说:
当
bWaitAll
为TRUE
时,仅当所有对象的状态都设置为已发出信号时,函数的等待操作才完成。在所有对象的状态都设置为已发出信号之前,该函数不会修改指定对象的状态。例如,可以向互斥体发出信号,但在其他对象的状态也设置为已发出信号之前,线程不会获得所有权。与此同时,其他一些线程可能会获得互斥锁的所有权,从而将其状态设置为非信号。
文档是错误的,还是我的错误?
为什么WaitForMultipleObjectsEx
在 APC 执行期间获取互斥锁,即使它知道无论如何它永远不会获取互斥锁(因为执行 APC 意味着它将返回WAIT_IO_COMPLETE
,永远不会获取互斥锁)?