Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C pthreads中的条件变量和实时优先级_C_Pthreads_Thread Priority - Fatal编程技术网

C pthreads中的条件变量和实时优先级

C pthreads中的条件变量和实时优先级,c,pthreads,thread-priority,C,Pthreads,Thread Priority,我有两个线程,一个生产者和一个消费者。生产者线程通过命名管道以不同的速率接收来自另一个程序的数据,并通过队列将其转发给使用者线程。调度程序策略为RR,并且生产者线程的优先级高于使用者线程。我希望生产者发出信号,表示队列中有新数据,并让使用者等待生产者阻塞,这将在没有数据可从指定管道读取时发生 主线程设置优先级: policy = SCHED_FIFO; pthread_attr_init(&tattr); pthread_attr_setinheritsched(&ta

我有两个线程,一个生产者和一个消费者。生产者线程通过命名管道以不同的速率接收来自另一个程序的数据,并通过队列将其转发给使用者线程。调度程序策略为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, &param);
pthread_create(&tid[0], &tattr, producer, fifo);

param.sched_priority = sched_get_priority_min(policy);
pthread_attr_setschedparam(&tattr, &param);
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);
}
发完信号后,低优先级线程接管。我做错了什么

提前谢谢

编辑:更改线程的名称。我在这里发布时更改了名称,因为我的代码是西班牙语,函数名不是producer-consumer,并且犯了一个错误。但不幸的是,事情并没有那么简单


我所说的“接管”是指消费者继续执行。我想让它在生产者线程阻塞或退出时启动。

如果您对“低优先级线程接管”的含义更清楚一点,这会很有帮助,因为这样更容易确定。但我不认为这与调度策略有任何关系

从POSIX规范可以,从,但相同的区别:

如果在一个条件变量上阻塞了多个线程,则调度策略将确定取消阻塞线程的顺序。当由于pthread_cond_信号或pthread_cond_广播而解除阻塞的每个线程从其对pthread_cond_wait或pthread_cond_timedwait的调用返回时,该线程拥有其调用pthread_cond_wait或pthread_cond_timedwait的互斥锁。被解除阻止的线程根据调度策略(如果适用)争夺互斥锁,就好像每个线程都调用了pthread_mutex_lock一样

现在,由于您的互斥体顺序,请参见最后一段中的注释,在执行pthread_cond_信号时,另一个线程不持有互斥体。因此,在单CPU机器上,我们知道无论调度策略如何,它都将被调度,因此,在信令线程设法重新锁定互斥锁之前,信令线程将立即捕获互斥锁。IE由于当时只有一个线程在争夺互斥对象,因此调度策略是不相关的,它总是会得到它

这就是你所指的吗

还有,如果你做了别的事情;在最短的时间内,您不希望在保持互斥锁的情况下执行此操作,否则将停止生产者的运行

这里可能还有另一件事在起作用。另一个问题可能是由于竞争条件,pthread_cond_信号无法工作。您不必在保持互斥的情况下调用pthread_cond_信号,但这是一个好主意。在本例中,例如,在使用者中,您在从队列中移除某些内容后解锁互斥锁,然后执行该信号。在删除互斥和发出信号之间,FIFO可能已经改变了状态,而引用FIFO->notFull在技术上是不安全的。我建议交换pthread_mutex_unlock和pthread_cond_信号;这也可以改进调度

编辑 现在是多余的,因为这是OP的错误,因为已修复

这真的很简单吗?您在原始邮件中说:

调度程序策略为RR,并且生产者线程的优先级高于使用者线程

但是,在代码中:

param.sched_priority = sched_get_priority_max(policy);
pthread_attr_setschedparam(&tattr, &param);
pthread_create(&tid[0], &tattr, consumerr, fifo);

param.sched_priority = sched_get_priority_min(policy);
pthread_attr_setschedparam(&tattr, &param);
pthread_create(&tid[1], &tattr, producer, fifo);
在我看来,消费者的优先级最高,生产者的优先级最低。

尝试在禁用优化的情况下编译您的项目,因为如果您现在启用了它们,并且变量fifo->empty和fifo->full没有声明为volatile,那么编译器很可能会以您不喜欢的方式优化代码的某些部分-该值只测试一次,如果这是真的,那么您的代码将陷入一个无止境的循环,即pthread_cond_wait的循环,它无论如何都不会离开,因为编译器看不到pthread_cond_wait如何改变它

如果不是这样,那么你描述的行为我还是不清楚。。。您的示例应按以下方式工作:

制作人在队列中放入一些东西,直到它满了,然后阻塞, 消费者从队列中取出商品,并向制作人发出信号,表示有一个空闲槽, producer醒来时假设它在读取时未被阻止,并将一个项目放入队列(即整个可用空间),然后阻止, ...
你看到的行为与你期望的有什么不同?当队列中没有数据时,消费者如何接管?它应该在第一个(也是从队列中获取的最后一个元素)之后停止接管,并等待生产者添加任何内容。

您所说的低优先级线程接管是什么意思?有你
您考虑过使用MQUE.h头中的消息队列将数据传输到使用者,并使用单个条件变量+共享易失性变量或信号量或信号向生产者发送信号?不,我没有尝试过。谢谢你的想法。那么,说清楚一点,你只想让消费者在FIFO为非空且生产者无法运行的情况下运行,例如,卡在阻塞读取中?与当前仅在满足前一个条件的情况下运行相反?@asCii88因此保持互斥锁也做些什么,因此互斥锁解锁的唯一点是它处于读取状态时,我认为这是您想要的。在原始代码中,解锁互斥锁和发信号通知条件变量的顺序非常好。你会发现到处都有这样的信息:如果悲观化,按照你的建议去做,只会导致过度的上下文切换。您不使用互斥体来同步对条件变量的访问,而是为了保护共享资源。正如我所说的,当条件变量发出信号时,不需要保持互斥体,但这并不免除您同步访问变量的要求。然而,我认为我是正确的,OP的排序将始终导致线程等待该互斥体获取它,这将始终导致上下文切换,如果下一个信令线程在这里做的事情是等待互斥体,请参阅下一个while循环的开始;如果互斥体上只有一个东西在等待,它就会得到它。它是最佳的还是最佳的取决于具体情况。将立即进行上下文切换。但在你的场景中会有。。。即时上下文切换甚至更早。如果在发出条件信号时保持互斥体,则发出信号的线程将被唤醒,并在互斥体上的等待功能块内,这将导致另一个上下文切换回信号线程,然后可以解锁互斥体,从而另一个上下文切换到发信号的线程。这是悲观的,因为这样你总是会得到这些额外的开关,而在相反的情况下,只有当你有一个像OP这样的循环时,上下文开关才会出现在这种情况下@弗雷德·肖邦不确定你是对的。但是,如果需要可预测的调度行为,则该互斥锁由调用pthread_cond_signal或pthread_cond_broadcast的线程锁定除非他们建议pessimal==可预测!我相信,在这种情况下,互斥体处理的工作方式与pthread_cond_wait类似,也就是说,它被视为调度,就好像互斥体被丢弃一样。无论如何,我们不应该在评论中争论这个问题。当生产者将某些内容放入队列并发出pthread\u cond\u signal fifo->notEmpty信号时,consumber解除阻塞,获取元素并运行。当然,当一次迭代后队列中什么都没有了时,它会阻塞,生产者会再次运行。