gpt4 book ai didi

c++ - Windows 临界区公平性

转载 作者:行者123 更新时间:2023-11-30 17:34:06 26 4
gpt4 key购买 nike

我对 Windows 上使用 EnterCriticalSection 和 LeaveCriticalSection 方法的关键部分的公平性有疑问。 MSDN 文档指出:“无法保证线程获得临界区所有权的顺序,但是系统对所有线程都是公平的。”问题出在我编写的一个应用程序上,它阻塞了一些永远不会进入临界区的线程,即使在很长一段时间后也是如此;所以我用一个简单的 C 程序执行了一些测试,以验证这种行为,但是当你有很多线程并且内部有一些等待时间时,我注意到奇怪的结果。这是测试程序的代码:

CRITICAL_SECTION CriticalSection;

DWORD WINAPI ThreadFunc(void* data) {
int me;
int i,c = 0;;
me = *(int *) data;
printf(" %d started\n",me);
for (i=0; i < 10000; i++) {
EnterCriticalSection(&CriticalSection);
printf(" %d Trying to connect (%d)\n",me,c);
if(i!=3 && i!=4 && i!=5)
Sleep(500);
else
Sleep(10);
LeaveCriticalSection(&CriticalSection);
c++;
Sleep(500);
}
return 0;
}

int main() {
int i;
int a[20];
HANDLE thread[20];

InitializeCriticalSection(&CriticalSection);
for (i=0; i<20; i++) {
a[i] = i;
thread[i] = CreateThread(NULL, 0, ThreadFunc, (LPVOID) &a[i], 0, NULL);
}
}

这样做的结果是,有些线程被阻塞了很多周期,而另一些线​​程则经常进入临界区。我还注意到,如果你改变更快的 sleep (10 毫秒),一切可能都会恢复公平,但我没有发现 sleep 时间和公平之间有任何联系。然而,这个测试示例比我的真实应用程序代码要好得多,后者要复杂得多,并且实际上显示了某些线程的饥饿情况。为了确保饥饿的线程处于事件状态并正常工作,我做了一个测试(在我的应用程序中),在关键部分中输入 5 次后我杀死线程:结果是,最后,每个线程都进入,所以我确保它们全部都处于事件状态并且被互斥锁阻塞。我是否必须假设 Windows 对于线程确实不公平?您知道这个问题有什么解决办法吗?

编辑:Linux 中使用 pthreads 的相同代码,按预期工作(没有线程匮乏)。

EDIT2:我找到了一个可行的解决方案,使用 CONDITION_VARIABLE 强制公平。可以从这篇文章( link )中推断出来,并进行必要的修改。

最佳答案

无论如何,你都会在这里遇到饥饿问题,因为关键部分被保留了很长时间。
我认为 MSDN 可能建议调度程序在唤醒线程方面是公平的,但由于没有锁获取顺序,因此它实际上可能并不像您期望的那样“公平”。您是否尝试过使用互斥体而不是关键部分?另外,您是否尝试过调整旋转计数?

如果您可以避免长时间锁定关键部分,那么这可能是处理此问题的更好方法。

例如,您可以重构代码,让一个线程处理长时间运行的操作,其他线程将对该线程的请求排队,并在完成事件上阻塞。管理队列时只需要短时间锁定临界区即可。当然,如果这些操作还必须与其他操作互斥,那么您需要小心。如果所有这些东西不能同时操作,那么您也可以通过队列对其进行序列化。

或者,也许可以看看使用 boost asio。您可以使用线程池和链来防止多个异步处理程序同时运行,否则同步会成为问题。

关于c++ - Windows 临界区公平性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23515630/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com