【问题标题】:Waiting on multiple semaphores without busy-waiting (C/C++ Linux)等待多个信号量而不忙等待(C/C++ Linux)
【发布时间】:2011-12-08 12:10:28
【问题描述】:

如果我有多个信号量,在至少一个信号量空闲之前,我如何才能让进程阻塞?我知道我可以通过忙等待循环来做到这一点,例如:

// 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 技术?

谢谢

【问题讨论】:

  • 不使用信号量,使用条件变量怎么样?

标签: c++ c linux ipc semaphore


【解决方案1】:

Here (developers.sun.com, via the Internet Archive) 是 Sun 的一篇简短论文,介绍了他们如何在 Solaris 中实现 WaitForMultipleObjects 仿真。基本思想是将条件变量列表与句柄(受互斥体保护)相关联,并在句柄发出信号时向所有条件变量发出信号。每次调用模拟的WaitForMultipleObjects 时,都会创建一个新的条件变量并将其添加到您感兴趣的所有句柄列表中。在WaitForMultipleObjects 模拟中,您阻塞条件变量,并检查每个句柄你醒了。

存在条件变量列表(而不是单个)的原因是您可能有两个线程在句柄上阻塞:线程 1 在 A 和 B 上阻塞,线程 2 在 A 和 C 上阻塞。发信号通知 B 不应唤醒线程 2。由于每次调用 WaitForMultipleObjects 都会创建一个新的条件变量,因此在这种情况下,B 和 C 将各有一个不同的条件变量,而 A 将同时拥有这两个条件变量。

如需更多详细信息,您需要阅读文章本身。

【讨论】:

  • Sun 站点已删除链接的 URL。互联网档案馆有一份:https://web.archive.org/web/*/http://developers.sun.com/solaris/articles/waitfor_api.pdf
  • 这里建议的解决方案允许等待所有或任何(基于函数参数选择)类型为solaris_win32_event_t 的“事件”。这是一个(有点过时?)如何实现订阅模型的示例,但没有提供问题的答案。所以这个“解决方案”需要先解决问题,然后才能使用它 - 通过在单独的线程中等待每个信号量,并从那里发出“事件”信号。
【解决方案2】:

使用多个单独的等待者线程,如:

  • 每个线程等待一个单独的信号量。
  • 在成功等待信号量后,任何给定的等待者线程都会向想要“等待多个信号量”的线程发出信号(通过另一个信号量、条件变量或任何最方便的原语)。

【讨论】:

  • 看来这个“解决方案”需要你先解决问题才能使用。所以现在等待线程需要等待多个“最方便的原语”才能全部变为信号量而不是多个信号量。似乎并不容易。
  • 不,它等待单个原语,任何单独的服务员线程都会发出信号。就像线程 A 在 sem A 上等待一样,线程 B 在 sem B 上等待,线程 C 在 sem C 上等待,但是一旦成功,它们中的任何一个都会发布到主服务员正在等待的 sem X。当然,在现实中你会想要让它更漂亮一点,这样主服务员就知道哪个成功了。
  • 哦,我被 vhallac 提到的 WaitForMultipleObjects 弄糊涂了,它可以等待 ALL。等待任何一个都很容易,只需使用selectpoll
  • selectpoll 不能等待信号量本身。您可以将管道与 select/poll 一起用于所有帮助线程,作为我提到的共享同步对象,但为此目的它们比信号量慢 10 到 1000 倍...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-21
  • 1970-01-01
  • 1970-01-01
  • 2014-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多