c - 使用 Windows API 使用互斥锁方法创建 100 个线程导致意外结果,如何解决?
问题描述
我目前正在使用一个简单的多线程程序尝试来自<windows.h>的 API,该程序以同步方式打印每个线程的给定索引,每个打印操作之间有 1 秒的延迟。
这个程序是用 C 编写的,但我想它在 C++ 中是一样的。
这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define THREAD_LEN 100
HANDLE mutex_handle = NULL;
HANDLE thread_handle[THREAD_LEN];
DWORD WINAPI execute(LPVOID param) {
int id = *(int *) param;
if (WAIT_OBJECT_0 != WaitForSingleObject(mutex_handle, INFINITE)) {
printf("ERROR_CODE: %d\n", GetLastError());
}
printf("[%d]\n", id);
Sleep(1000);
ReleaseMutex(mutex_handle);
return 0;
}
int main(void) {
mutex_handle = CreateMutex(NULL, FALSE, NULL);
DWORD thread_id;
for (int i = 0; i < THREAD_LEN; i++) {
int *id = (int *) malloc(sizeof(int));
*id = i;
thread_handle[i] = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE) execute,
id,
0,
&thread_id);
if (!thread_handle[i]) {
return 1;
}
}
WaitForMultipleObjects(THREAD_LEN, thread_handle, TRUE, INFINITE);
for (int i = 0; i < THREAD_LEN; i++) {
CloseHandle(thread_handle[i]);
}
CloseHandle(mutex_handle);
return 0;
}
但它显示出意外的行为:当我通过 cmd 运行它时,方法 Sleep(1000) 不起作用(程序不会每秒打印一个 id,而是一次突发),并且并非所有线程都打印出它们的 id .
[0]
ERROR_CODE: 6
ERROR_CODE: 6
[30]
ERROR_CODE: 6
[5]
[29]
ERROR_CODE: 6
[33]
ERROR_CODE: 6
[34]
ERROR_CODE: 6
[41]
ERROR_CODE: 6
[37]
ERROR_CODE: 6
ERROR_CODE: 6
[47]
ERROR_CODE: 6
ERROR_CODE: 6
[55]
ERROR_CODE: 6
[43]
ERROR_CODE: 6
[44]
ERROR_CODE: 6
[38]
ERROR_CODE: 6
ERROR_CODE: 6
[17]
ERROR_CODE: 6
[50]
ERROR_CODE: 6
[76]
ERROR_CODE: 6
[11]
[36]
ERROR_CODE: 6
[42]
ERROR_CODE: 6
[57]
ERROR_CODE: 6
[13]
ERROR_CODE: 6
[58]
ERROR_CODE: 6
但是,当我将线程数减少到 60 时,程序确实在预期中工作。
[0]
[3]
[2]
[1]
[6]
[34]
[37]
[39]
[8]
[9]
[46]
[11]
[51]
[53]
[55]
[58]
[16]
[17]
[18]
[19]
[20]
[22]
[21]
[23]
[24]
[25]
[26]
[27]
[28]
[29]
[30]
[31]
[32]
[33]
[4]
[36]
[35]
[38]
[5]
[7]
[40]
[42]
[41]
[43]
[44]
[45]
[10]
[47]
[48]
[49]
[50]
[12]
[52]
[13]
[54]
[14]
[56]
[57]
[59]
[15]
解决方案
WaitForMultipleObjects 不能等待超过 64 个对象。减少您的等待,如果需要,一次生成更多线程等待 64 个。
尝试这样做会导致 WaitForMultipleObjects 立即返回,因此您立即关闭互斥体,而 WaitForSingleObject 抱怨互斥体已经关闭。
推荐阅读
- r - 如何重塑 R 中的相关输出(非透视结果数据)?
- android - 如何使用 asynctask 和字符串发送文件?
- kubernetes-go-client - 我可以使用 kubernetes 中的自定义调度程序更改未调度 Pod 的计算资源限制吗
- reporting-services - SSRS 加权平均总数除以零误差
- python-3.x - Python - plt.subplot() 在 for 循环中创建绘图
- c++ - 类模板的 C2760 编译器错误
- sql - 如何将同一张表中的 2 个查询与不同的 group by 组合起来?(甲骨文)
- javascript - React Native 数组道具混淆
- python - Python名称错误8
- mysql - SQL查询天数差异