我有一个多线程应用程序,它有一个生产者 - 消费者模型。
基本上我有2个结构。
第一个是一个结构,它包含了要完成的工作的所有必要信息。
第二个是绑定到工作线程的结构,它包含指向第一个结构的指针。
像这样:typedef struct worker_struct {
/* information for the work to be done */
} worker_struct;
typedef struct thread_specs {
worker_struct *work;
unsigned short thread_id;
unsigned short pred_cond;
pthread_mutex_t busy_mutex;
pthread_cond_t work_signal;
} thread_specs;
现在这一切都很好,但是现在从我的制作人那里我知道哪些工作需要完成,我想将工作线程链接起来完成工作。我的问题是我不知道如何判断我的工作线程当前是否正忙。
我有条件等待的谓词条件,如下所示:
while ( thread_stuff->pred_cond == 0 ) {
retval = pthread_cond_wait( &(thread_stuff->work_signal), &(thread_stuff->busy_mutex);
if (retval !=0 ) {
strerror_r(retval, strerror_buf, ERRNO_BUFSIZE);
printf("cond wait error! thread: %u, error: %s\n", thread_stuff->thread_id, strerror_buf);
}
}
现在我如何确保线程不忙。如果我设置了一个受互斥锁保护的变量,它从信号中醒来后,我得到一个竞争条件,因为我无法保证变量在我的消费者再次检查等待线程之前被设置。
我看到我能做的唯一方法就是使用与条件等待相同的互斥锁对其进行pthread_mutex_trylock()
,但这似乎有点昂贵且不优雅。
还有其他一些方法,更好的方法来做这样的事情,即判断一个线程当前是否在谓词条件下等待?
问候
答案 0 :(得分:2)
在典型的生产者 - 消费者关系中,生产者和消费者彼此断开连接,并通过一些共享数据结构(如FIFO队列)进行通信。生产者创造就业机会并将其置于队列中。消费者从队列中删除项目并处理它们。因此,生产者无需知道是否有可用的消费者。他们只是排队工作,下一个可用的消费者会选择它。
这样的设计使得添加或删除生产者或消费者变得容易,因为他们可以彼此独立。
如果您需要某种工作当前正在处理或完成的信号,您通常会使用某种信号机制,例如事件。
如果要限制已计划但尚未处理的工作项的数量,则会限制FIFO队列的大小。
答案 1 :(得分:1)
我的一个类似问题在一段时间后得到了很好的回答。
C - Guarantee condvars are ready for signalling
它保证你的condvar确实准备通过受保护的状态布尔值发出信号,这意味着它已经睡着了。如果您只是使用简单的设置(即:每个线程一个condvar),那么您可以使用它来检测线程是否处于睡眠状态。