我想实现生产者 - 消费者场景,其中有一个生产者线程和多个消费者线程。 实际上,具体来说,生产者线程需要定期创建一组对象(例如,5秒),并且消费者线程需要使用对象。
我不确定如何定期创建一组对象以及如何同步多个消费者。
提前致谢
答案 0 :(得分:2)
你究竟遇到了什么问题?传统上,工作队列受条件锁保护;如果多个“消费者”正在等待同一个锁,那么其中只有一个会成功获得它。但是,您应该从中获取一个对象,将其从队列中删除,然后在处理作业之前释放锁定,而不是抓取整个队列。
至于定期创建作业,这是您正在使用的任何库中的计时器类的工作。如果您正在等待输入,则select()和poll()调用具有超时值;如果你没有做任何事情,你可以打电话给[u] sleep()。
答案 1 :(得分:1)
我不会拼出所有代码,但您可以为此使用互斥锁和条件变量(以及链接列表)。基本模式是生产者做的:
loop_forever
wait_until_interval_has_elapsed
lock_the_mutex
append_an_item_to_the_list
signal_the_condvar // can be outside the mutex
unlock_the_mutex
每个消费者都这样做:
loop_forever
lock_the_mutex
while(list_is_empty)
wait_the_condvar
remove_an_item_from_the_list
unlock_the_mutex
process_the_item
您也可以使用互斥锁和信号量:
loop_forever
wait_until_interval_has_elapsed
lock_the_mutex
append_an_item_to_the_list
unlock_the_mutex
post_the_semaphore
loop_forever
wait_the_semaphore
lock_the_mutex
remove_an_item_from_the_list
unlock_the_mutex
process_the_item
这稍微简单,但是一旦你决定添加一种机制来告诉消费者完成他们正在做的事情并退出你可能会更好地使用条件变量,因为你可以“广播”它。信号量因易误用而略有声誉,这就是C ++ 11没有信号量的原因。但是,Posix确实在Linux上有你的选择。并且公平地说,大致所有其他多线程操作系统也是如此。
在线程具有不同优先级的情况下,互斥/ condvar对也可能比信号量提供更好的行为。与互斥锁不同,信号量没有“所有者”,因此优先级继承等技术是不可能的。
对于wait_until_interval_has_elapsed
使用计时器或睡眠功能 - 请注意,除非您使用的是实时系统,否则您永远无法确定您是否能够在特定时间运行,只有您能够在特定时间或之后被唤醒。
答案 2 :(得分:1)
您需要一种方法来告诉消费者线程有新对象可用。这是一个例子(我没有包含#include
):
#define NUM_CONSUMERS 2
static int objects[4]; //The place for produced objects
static pthread_mutex_t cond_mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* producer_func(void* arg);
void* consumer_func(void* arg);
int main(int argc, char** argv) {
pthread_t producer;
pthread_t consumers[NUM_CONSUMERS];
int res;
void* zero = 0;
res = pthread_create(&producer, NULL, producer_func, zero);
for(int i = 0; i < NUM_CONSUMERS; i++) {
res = pthread_create(&consumers[i], NULL, consumer_func, zero);
}
}
void* producer(void* arg) {
while(1) {
objects[0] = 0;
objects[1] = 1;
objects[2] = 2;
objects[3] = 3;
pthread_mutex_lock(&cond_mut);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&cond_mut);
sleep(5);
}
}
void* consumer(void* arg) {
while(1) {
pthread_mutex_lock(&cond_mut);
pthread_cond_wait(&cond);
pthread_mutex_unlock(&cond_mut);
//Process objects here
}
}