如何用信号通知工作线程有一些工作要做?

时间:2020-02-02 09:13:39

标签: c multithreading sockets pthreads

我正在构建一个小型套接字服务器,我想在其中创建线程池,然后以boss-worker线程模式工作。因此,只要主(老板)收到请求,该请求就会从池传递到一个工作线程中。

在以下代码段中,我尝试创建10个线程。

void* process_data(void* arg) {
    printf("invoked by the created thread");
    while(1) {
          // sleep until woken
          // get item from queue
          // do something
    }
}

int total_threads_to_create = 10;
int total_created = 0;
while(total_created < 10) {
   // create 10 threads
   pthread_t thread;
   int created = pthread_create(&thread, NULL, process_data, NULL);
   if(created == 0) total_created++;
}

while(1) {
   // server accepts the request in an infinite loop
   int socket_fd = accept(ss_fd, (struct sockaddr*)&client_sock,&client_sock_len);

   put_new_request_in_queue();
   // signal to one of the thread that work is available

}

如您所见,每个新线程都直接调用process_data方法。现在,我要使process_data中的线程休眠,直到被主线程唤醒为止。

我如何:

  • 使process_data中的线程进入睡眠状态直到被主线程唤醒?
  • 如何向工作线程发信号通知有待处理的请求?

2 个答案:

答案 0 :(得分:1)

通常的解决方案是条件变量和队列。这里的一般模式称为生产者/消费者模式。

您可以使用互斥锁保护队列,然后使用条件变量唤醒工作人员

制作人

workToDo = generateSomeWork()
acquire mutex
queue.push(workToDo)
cv.notify();
release mutex

消费者

loop:
    acquire mutex
    while queue empty
        wait on cv (releasing mutex while waiting)
    workToDo = queue.pop()
    release mutex
    do(workToDo)

个人而言,我还喜欢添加一个布尔标志done,该标志在所有工人清理时都设置为True。因此,当您想干净地退出程序时,您需要获取互斥锁,将done设置为true,然后在cv上广播,这将唤醒所有工作。他们看到done已设置,并干净地终止。

答案 1 :(得分:0)

您有一个生产者-消费者,请使用信号量

您已经编写了"Producer-Consumer Problem"的示例。

管理生产者-消费者队列的最合适的控制机制是使用semaphore

您还需要锁定共享队列

但是,由于您有多个生产者,因此您还需要一个mutex以确保没有两个生产者线程尝试同时写入输出队列(如果没有,则将破坏您的队列数据结构)。

针对Producer-Consumer的Wikipedia文章为您提供了一个概述解决方案,但并未使用与您使用的pthreads库完全相同的函数名。

Pthreads信号量实现

pthreads库通过sem_t类型和sem_wait()(“等待”)和sem_post()(“信号”)调用实现信号。