我正在尝试学习pthread_cond_wait的基础知识。在所有用法中,我都看到了
if(cond is false)
pthread_cond_wait
或
while(cond is false)
pthread_cond_wait
我的问题是,我们想要cond_wait只是因为条件是假的。那么为什么我要明确地设置一个if / while循环的痛苦。我可以理解,如果在cond_wait
之前没有任何if / while检查,我们将直接点击它,它根本不会返回。条件检查仅用于解决此目的还是具有其他意义。如果它用于解决不必要的条件等待,那么进行条件检查并避免使用cond_wait类似于轮询?我正在使用这样的cond_wait。
void* proc_add(void *name){
struct vars *my_data = (struct vars*)name;
printf("In thread Addition and my id = %d\n",pthread_self());
while(1){
pthread_mutex_lock(&mutexattr);
while(!my_data->ipt){ // If no input get in
pthread_cond_wait(&mutexaddr_add,&mutexattr); // Wait till signalled
my_data->opt = my_data->a + my_data->b;
my_data->ipt=1;
pthread_cond_signal(&mutexaddr_opt);
}
pthread_mutex_unlock(&mutexattr);
if(my_data->end)
pthread_exit((void *)0);
}
}
逻辑是,我要求输入线程在输入可用时处理数据,并通知输出线程打印它。
答案 0 :(得分:20)
您需要一个while循环,因为即使未达到您正在等待的条件,调用pthread_cond_wait
的线程也可能会唤醒。这种现象称为“虚假唤醒”。
这不是错误,它是条件变量的实现方式。
这也可以在手册页中找到:
来自pthread_cond_timedwait()或的虚假唤醒 可能会发生pthread_cond_wait()函数 。自从归来 pthread_cond_timedwait()或pthread_cond_wait()并不意味着 关于这个谓词的值,谓词应该是 在返回时重新评估。
有关实际代码的更新:
void* proc_add(void *name)
{
struct vars *my_data = (struct vars*)name;
printf("In thread Addition and my id = %d\n",pthread_self());
while(1) {
pthread_mutex_lock(&mutexattr);
while(!my_data->ipt){ // If no input get in
pthread_cond_wait(&mutexaddr_add,&mutexattr); // Wait till signalled
}
my_data->opt = my_data->a + my_data->b;
my_data->ipt=1;
pthread_cond_signal(&mutexaddr_opt);
pthread_mutex_unlock(&mutexattr);
if(my_data->end)
pthread_exit((void *)0);
}
}
}
答案 1 :(得分:10)
您必须在等待之前测试互斥锁下的条件,因为条件变量的信号没有排队(条件变量不是信号量)。也就是说,如果一个线程在该条件变量的pthread_cond_signal()
中没有阻塞线程时调用pthread_cond_wait()
,那么该信号什么都不做。
这意味着如果您有一个线程设置条件:
pthread_mutex_lock(&m);
cond = true;
pthread_cond_signal(&c);
pthread_mutex_unlock(&m);
和然后另一个线程无条件地等待:
pthread_mutex_lock(&m);
pthread_cond_wait(&c, &m);
/* cond now true */
这第二个线程会永远阻止。通过让第二个线程检查条件来避免这种情况:
pthread_mutex_lock(&m);
if (!cond)
pthread_cond_wait(&c, &m);
/* cond now true */
由于cond
仅在保持互斥锁m
的情况下进行修改,这意味着当且仅当cond
为假时,第二个线程才会等待。
在健壮的代码而不是while ()
中使用if ()
循环的原因是因为pthread_cond_wait()
不能保证它不会虚假地唤醒。使用while ()
也意味着发出条件变量的信号始终是完全安全的 - “额外”信号不会影响程序的正确性,这意味着您可以执行诸如将信号移出锁定的代码段之外的操作。