我正在构建一个小型套接字服务器,我想在其中创建线程池,然后以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
中的线程进入睡眠状态直到被主线程唤醒?答案 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库通过sem_t
类型和sem_wait()
(“等待”)和sem_post()
(“信号”)调用实现信号。