2011-10-15 77 views
3

如果我有多个信号量,那么在至少有一个信号量空闲之前如何获得进程块?我知道我可以如用忙等待循环做到这一点:等待多个信号而无需等待(C/C++ Linux)

// blocks until one of the semaphores in sems is free, returns 
// index of semaphore that was available 
int multiple_sem_wait(sem_t **sems, int num_sems) { 
    while (true) { 
     for (int i = 0; i < num_sems; ++i) { 
     if (sem_trywait(sems[i]) == 0) { 
      return i; 
     } 
     } 
    } 
} 

但是,有没有办法做到这一点没有一个繁忙的循环?也许除了应该使用的信号量外,还有一些IPC技术?

感谢

+2

而不是使用信号量,如何使用条件变量? –

回答

4

Here (developers.sun.com)是来自Sun他们如何实现他们的WaitForMultipleObjects仿真在Solaris中很短的纸张。基本的想法是将一个条件变量列表关联到一个句柄(受互斥锁保护),并在发送句柄时发信号通知所有条件变量。每次调用模拟的WaitForMultipleObjects时,都会创建一个新的条件变量并将其添加到您感兴趣的所有句柄的列表中。在WaitForMultipleObjects仿真中,您将禁用条件变量,并在醒来时检查每个句柄。

条件变量列表(而不是单个列表)的原因是您可能在句柄上有两个线程阻塞:线程1在A和B上被阻塞,并且线程2在A和C上被阻塞。信号B不应该唤醒线程2.因为每次调用WaitForMultipleObjects都会创建一个新的条件变量,在这种情况下,B和C每个都会有一个不同的条件变量,而A将同时具有两个条件变量。

有关更详细的信息,您需要阅读文章本身。

+1

Sun网站已删除链接的网址。 Internet Archive有一个副本:[https://web.archive.org/web/*/http://developers.sun.com/solaris/articles/waitfor_api.pdf](https://web.archive.org /web/*/http://developers.sun.com/solaris/articles/waitfor_api.pdf) –

+0

这里提出的解决方案允许等待所有或任何(根据函数参数选择)“solaris_win32_event_t类型的事件” '。这是一个(有点过时的?)如何实现订阅模型的例子,但没有提供问题的答案。因此,这个“解决方案”需要先解决问题,然后才能使用它 - 通过在单独的线程中等待每个信号量并从那里发信号通知“事件”。 – Zrin

0

使用多个独立的服务员线程,如:

  • 在一个单独的信号的每个线程等待。
  • 在成功等待信号量后,任何给定的服务器线程信号(通过另一个信号量,条件变量或任何原语是最方便的)想要“等待多个信号量”的线程。
+0

看来这个“解决方案”要求您在使用它之前解决问题。所以现在等待的线程需要等待多个“任何最方便的原语”才能变成信号而不是多个信号量。似乎并不容易。 –

+0

不,它等待任何单独的服务器线程发出信号的单个原语。正如线程A在sem A上等待一样,线程B在sem B上等待,线程C在sem C上等待,但是如果成功,它们中的任何一个都会发送到主服务器正在等待的sem X上。当然,实际上你会想让它变得更有趣,所以主要的服务员知道哪一个成功了。 –

+0

哦,我对vhallac提到的可以等待ALL的'WaitForMultipleObjects'感到困惑。等待任何事情都很简单,只需使用'select'或'poll'即可。 –