4

我必须编写一个使用 CURL 在 Web 上发布信息的 C 应用程序。应用程序最多只能并行运行 N 个(比如说 10 个)请求。如何等待任何线程完成,而不是使用pthread_join().

我阅读了有关 pthread_cond_wait 的信息,但大多数示例是控制线程(主)如何唤醒工作线程。我需要相反的——工作线程必须能够在退出之前发出信号/唤醒父线程。

更新:实际上我需要一种让管理器线程休眠的方法,当一个工作线程完成它的工作时,它应该唤醒管理器线程给它另一个工作。线程是否结束并为作业创建新线程或使用线程池都没有关系。仍然需要一种方法来向经理发出工作已完成的信号。

我希望我不要得到这个建议

while(asleep){
  for(i = 0; i< threadCount; i++){
    pthread_mutex_lock(mutex);
    if(threads[i] == IDLE_STATE)
      startNewJob();
    pthread_mutex_unlock(mutex);
    usleep(100*1000);
  }
}
4

3 回答 3

4

与其按需创建/销毁线程,不如在启动时创建一个由 10 个工作线程组成的池并让您的主程序为它们提供作业。

在启动时,您将创建一个包含 10 个工作人员的数组。这些可能看起来像

typedef struct worker
{
    pthread_t       thread;
    pthread_cond_t  cond;
    pthread_mutex_t mutex;
    struct job*     job;
    int             quit;
} worker;

job经理将通过设置其成员然后向工作人员发出信号来依次将作业委托给每个线程。

每个工人都会循环直到quit非零,等待它的条件被发出信号。在每个信号之后,它会在报告结果之前读取/处理它job,然后再次等待它的条件。

编辑:您不热衷于线程池。您可以尝试给每个线程一个唯一的 id;在管理器中存储每个线程的 id 和其他属性之间的一些映射。当每个线程完成时,让它将其 id 添加到管理器拥有的列表中,然后在管理器中发出一个条件信号。每次经理醒来时,它可以从列表中拉出头部,查找适当的线程,读回其作业结果,然后加入线程。请注意,此处的管理器列表将由多个线程访问,因此读/写需要由互斥锁保护。

Edit2:您想了解更多有关条件的信息,但找不到您认为有用的示例。我不确定这会更好,但这是我编写的一些代码。这些OsSemaphore*函数将条件包装到一个简单的等待/信号 API 中。

于 2012-12-13T11:02:52.257 回答
1

您想要一个条件变量,与您一直在查看的相同功能,但只是转过身来。您正在等待的条件是“工作线程已完成一些工作”。

主线程:

  • 锁定互斥锁
  • 虽然没有线程完成:pthread_cond_wait
  • 解锁互斥锁
  • 安排工作
  • 环形

每个工作线程在完成工作时会:

  • 锁定互斥锁
  • 标记完成
  • pthread_cond_signal
  • 解锁互斥锁
  • 退出或等待工作
于 2012-12-14T16:24:17.967 回答
1

条件变量是你所追求的。它们可以很容易地用于从工作线程向管理器线程发出信号,反之亦然。

最后的稻草人示例实际上与使用条件变量可以执行的操作非常相似:

pthread_mutex_lock(&mutex);
while (!finished) {
  for(i = 0; i < threadCount; i++) {
    if(threads[i] == IDLE_STATE)
      startNewJob(i);
  }

  /* Not finished, and no idle threads, so wait */
  if (!finished)
    pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);

当一个线程完成时,它会简单地做:

pthread_mutex_lock(&mutex);
threads[self] = IDLE_STATE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
于 2012-12-15T03:01:31.727 回答