首页 > 解决方案 > WaitForSingleObject() 中的早期唤醒...?

问题描述

我在 MS 文档站点(没有真正解决)和 SO 中读到的所有内容都表示,WindowsWaitForSingleObject()不会受到虚假唤醒的影响,它至少会等待提供的时间,甚至可能更长。然而,我的测试表明这不是真的,事实上早醒几乎总是发生。“常识”是错误的,我只需要添加循环来处理早期唤醒,还是我做错了什么,我需要继续努力解决这个问题?

不幸的是,完整的代码太复杂了,无法在这里发布,但我有两个不同的线程,每个线程都有自己的事件,通过以下方式创建:

event = CreateEventA(NULL, false, false, NULL);

(事件是线程局部变量)。我有一个互斥锁,用于确保两个线程几乎同时开始运行。

在我调用的每个线程WaitForSingleObject()中。在这个特定的测试中,我从不调用SetEvent(),所以完成的唯一方法是通过超时,返回代码显示这就是发生的情况。然而,实际花费的等待时间变化很大,90% 的时间少于我要求的时间。我已经对此进行QueryPerformanceCounter()了检测,以检测在这里花费了多长时间,这是错误的。这是检测代码:

LARGE_INTEGER freq, ctr1, ctr2;
QueryPerformanceFrequency(&freq);

QueryPerformanceCounter(&ctr1);
DWORD ret = WaitForSingleObject(event, tmoutMs);
QueryPerformanceCounter(&ctr2);

uint64_t elapsed = ((uint64_t)ctr2.QuadPart - (uint64_t)ctr1.QuadPart) * 1000000ULL / (uint64_t)freq.QuadPart;

(这里elapsed以微秒为单位,只是为了更具体一点)然后我打印出这个信息。在一个线程tmoutMs中是 2,而在另一个线程tmoutMs中是 100。几乎每次返回的值都太短:2 毫秒的等待可能需要 700 毫秒以上的任何时间,而 100 毫秒的等待时间可能需要大约 93 毫秒。只有在 7 次左右的尝试中,经过的时间才会 > 100 毫秒。以下是一些示例输出:

event=104: pause(tmoutMs=2) => ret=258 elapsed us=169, ms=0
event=112: pause(tmoutMs=100) => ret=258 elapsed us=93085, ms=93

event=104: pause(tmoutMs=2) => ret=258 elapsed us=427, ms=0
event=112: pause(tmoutMs=100) => ret=258 elapsed us=94002, ms=94

event=104: pause(tmoutMs=2) => ret=258 elapsed us=3317, ms=3
event=112: pause(tmoutMs=100) => ret=258 elapsed us=96840, ms=96

event=104: pause(tmoutMs=2) => ret=258 elapsed us=11461, ms=11
event=112: pause(tmoutMs=100) => ret=258 elapsed us=105189, ms=105

如预期的那样,返回码始终是 WAIT_TIMEOUT。

这是合理的,即使它没有记录(或者它记录在我找不到的某个地方),我只需要自己循环处理早期唤醒吗?

FWIW,这是一个用 Visual Studio 2017 编译的 C++ 程序,在 Windows10 上运行。它是一个使用 Google Test 的单元测试程序,没有图形界面:它只是命令行。

标签: windowsmultithreadingtime

解决方案


推荐阅读