我有两个线程,一个生产者和一个消费者。生产者线程通过命名管道以不同的速率从另一个程序接收数据,并通过队列将其转发到消费者线程。调度策略为RR,生产者线程的优先级高于消费者线程。我希望生产者发出信号,表明队列中有新数据,并让消费者等待,直到生产者阻塞,当没有数据可从命名管道读取时,就会发生这种情况。
主线程设置优先级:
policy = SCHED_FIFO;
pthread_attr_init(&tattr);
pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setschedpolicy(&tattr, policy);
param.sched_priority = sched_get_priority_max(policy);
pthread_attr_setschedparam(&tattr, ¶m);
pthread_create(&tid[0], &tattr, producer, fifo);
param.sched_priority = sched_get_priority_min(policy);
pthread_attr_setschedparam(&tattr, ¶m);
pthread_create(&tid[1], &tattr, consumer, fifo);
制作人这样做:
fd = open(pipe, O_RDONLY);
while((read(fd, buf, 1024))!=0){
val = atoi(buf);
if(val > SOMETHING){
do_something();
} else {
pthread_mutex_lock (fifo->mut);
while (fifo->full) {
pthread_cond_wait (fifo->notFull, fifo->mut);
}
queueAdd (fifo, val);
pthread_mutex_unlock (fifo->mut);
pthread_cond_signal (fifo->notEmpty);
}
}
消费者:
while(TRUE){
pthread_mutex_lock (fifo->mut);
while (fifo->empty) {
pthread_cond_wait (fifo->notEmpty, fifo->mut);
}
queueDel (fifo, &d);
do_something_else(d);
pthread_mutex_unlock (fifo->mut);
pthread_cond_signal (fifo->notFull);
}
发出信号后,优先级较低的线程接管。我做错了什么?
提前致谢!
编辑:更改了线程的名称。我在此处发布时更改了名称,因为我的代码是西类牙语,并且函数名称不是生产者消费者,并且犯了一个错误。但不幸的是事情没那么简单。
我所说的“接管”是指消费者继续执行。我想要的是当且仅当生产者线程阻塞或退出时它才启动。
最佳答案
尝试使用优化来编译您的项目禁用,因为如果您现在启用它们并且变量 fifo->empty 和 fifo->full NOT 声明为 volatile ,那么编译器很可能会以您不喜欢的方式优化代码的某些部分 - 该值仅测试一次,如果是这样,您的代码就会陷入无限循环(带有 pthread_cond_wait()
)无论如何它都不会离开,因为编译器无法看到pthread_cond_wait()
如何改变它。
如果不是这样,那么我仍然不清楚您所描述的行为...您的示例应该按以下方式工作:
- 生产者将一些内容放入队列中,直到队列满,然后阻塞,
- 消费者从队列中取出一项,并向生产者发出信号,表明有一个空闲槽位,
- 生产者醒来(假设它在
read()
上没有被阻塞)并将一项放入队列(即整个可用空间),然后阻塞, - ...
您看到的行为与您期望的有何不同?当队列中没有数据时,消费者如何“接管”?它应该在从队列中取出第一个(也是最后一个)元素后停止“接管”,并等待生产者添加任何内容。
关于pthread 中的条件变量和实时优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27134152/