c – ReleaseSemaphore不释放信号量

(简而言之: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),它们也更容易理解.

上一篇:Java中的synchronized方法和synchronized块之间有什么区别?


下一篇:java – Integer对象的synchronized块