(简而言之:main()的WaitForSingleObject在下面的程序中挂起).
我正在尝试编写一段代码来调度线程并等待它们在恢复之前完成.我不是每次创建线程都是昂贵的,而是让它们进入睡眠状态.主线程在CREATE_SUSPENDED状态下创建X线程.
使用X作为MaximumCount的信号量完成同步.信号量的计数器被降低到零并且线程被分派. threds执行一些愚蠢的循环并在他们进入睡眠之前调用ReleaseSemaphore.然后主线程使用WaitForSingleObject X次,以确保每个线程完成其工作并正在休眠.然后它循环并再次完成所有操作.
程序不时会退出.当我喙程序时,我可以看到WaitForSingleObject挂起.这意味着线程的ReleaseSemaphore不起作用.没有什么是打印的,所以据说没有出错.
也许两个线程不应该在同一时间调用ReleaseSemaphore,但这会使信号量的目的无效……
我只是不理睬它……
我们非常感谢其他同步线程的解决方案!
#define TRY 100
#define LOOP 100
HANDLE *ids;
HANDLE semaphore;
DWORD WINAPI Count(__in LPVOID lpParameter)
{
float x = 1.0f;
while(1)
{
for (int i=1 ; i<LOOP ; i++)
x = sqrt((float)i*x);
while (ReleaseSemaphore(semaphore,1,NULL) == FALSE)
printf(" ReleaseSemaphore error : %d ", GetLastError());
SuspendThread(ids[(int) lpParameter]);
}
return (DWORD)(int)x;
}
int main()
{
SYSTEM_INFO sysinfo;
GetSystemInfo( &sysinfo );
int numCPU = sysinfo.dwNumberOfProcessors;
semaphore = CreateSemaphore(NULL, numCPU, numCPU, NULL);
ids = new HANDLE[numCPU];
for (int j=0 ; j<numCPU ; j++)
ids[j] = CreateThread(NULL, 0, Count, (LPVOID)j, CREATE_SUSPENDED, NULL);
for (int j=0 ; j<TRY ; j++)
{
for (int i=0 ; i<numCPU ; i++)
{
if (WaitForSingleObject(semaphore,1) == WAIT_TIMEOUT)
printf("Timed out !!!\n");
ResumeThread(ids[i]);
}
for (int i=0 ; i<numCPU ; i++)
WaitForSingleObject(semaphore,INFINITE);
ReleaseSemaphore(semaphore,numCPU,NULL);
}
CloseHandle(semaphore);
printf("Done\n");
getc(stdin);
}
解决方法:
问题发生在以下情况:
主线程恢复工作线程:
for (int i=0 ; i<numCPU ; i++)
{
if (WaitForSingleObject(semaphore,1) == WAIT_TIMEOUT)
printf("Timed out !!!\n");
ResumeThread(ids[i]);
}
工作线程完成他们的工作并释放信号量:
for (int i=1 ; i<LOOP ; i++)
x = sqrt((float)i*x);
while (ReleaseSemaphore(semaphore,1,NULL) == FALSE)
主线程等待所有工作线程并重置信号量:
for (int i=0 ; i<numCPU ; i++)
WaitForSingleObject(semaphore,INFINITE);
ReleaseSemaphore(semaphore,numCPU,NULL);
主线程进入下一轮,尝试恢复工作线程(请注意,工作线程尚未暂停事件!这是问题开始的地方……您正在尝试恢复未必暂停的线程然而):
for (int i=0 ; i<numCPU ; i++)
{
if (WaitForSingleObject(semaphore,1) == WAIT_TIMEOUT)
printf("Timed out !!!\n");
ResumeThread(ids[i]);
}
最后工作线程暂停(尽管它们应该已经开始下一轮):
SuspendThread(ids[(int) lpParameter]);
由于所有工人现在都被停职,主线程永远等待:
for (int i=0 ; i<numCPU ; i++)
WaitForSingleObject(semaphore,INFINITE);
这是一个链接,显示如何正确解决生产者/消费者问题:
http://en.wikipedia.org/wiki/Producer-consumer_problem
我认为critical sections比信号量和互斥量快得多.在大多数情况下(imo),它们也更容易理解.