简体   繁体   English

pthread_cond_wait没有从pthread_cond_broadcast唤醒

[英]pthread_cond_wait not waking up from pthread_cond_broadcast

in my program there's a part of code that waits to be waken up from other part of code: 在我的程序中,有一部分代码等待被其他代码唤醒:
Here's the part that goes to sleep: 这是睡觉的部分:

void flush2device(int task_id) {

if (pthread_mutex_lock(&id2cvLock) != SUCCESS) {
    cerr << "system error - exiting!!!\n";
    exit(1);
}

map<int,pthread_cond_t*>::iterator it;

it = id2cv.find(task_id);

if(it == id2cv.end()){

    if (pthread_mutex_unlock(&id2cvLock) != SUCCESS) {
        cerr << "system error\n UNLOCKING MUTEX flush2device\n"; 
        exit(1);
    }

    return;
}

cout << "Waiting for CV signal" <<endl;

if(pthread_cond_wait(it->second, &id2cvLock)!=SUCCESS){
    cerr << "system error\n COND_WAIT flush2device - exiting!!!\n";
    exit(1);
}
cout << "should be right after " << task_id << " signal" << endl;


if (pthread_mutex_unlock(&id2cvLock) != SUCCESS) {
    cerr << "system error\n UNLOCKING MUTEX flush2device -exiting!!!\n"; 
    exit(1);
}

} }
In another part of code, there's the waking up part (signaling): 在代码的另一部分中,有唤醒部分(信令):

//id2cv is a map <int, pthread_cond_t*> variable. - the value is a pointer to the cv on
//which we call with the broadcast method.
if(pthread_mutex_lock(&id2cvLock)!=SUCCESS){
    cerr <<"system error\n";
    exit(1);
}

id2cv.erase(nextBuf->_taskID);

cout << "In Thread b4 signal, i'm tID " <<nextBuf->_taskID << endl;
    if (pthread_cond_broadcast(nextBuf->cv) != 0) {
        cerr << "system error SIGNAL_CV doThreads\n";
        exit(1);
    }
cout << "In doThread, after erasing id2cv " << endl;
if(pthread_mutex_unlock(&id2cvLock)!=SUCCESS){
    cerr <<"system error\n;
    exit(1);
}  

Most of the runnings work just fine, but once in a while the program just stop "reacting" - the first method (above) just doesn't pass the cond_wait part - it seems like no one really send her the signal on time (or from some other reason) - while the other method (which the last part of code is a part of it) keeps running. 大多数运行情况都很好,但是程序偶尔会停止“反应”-第一种方法(上面)只是没有通过cond_wait部分-似乎没有人真正按时发送信号(或(出于某种其他原因)-而其他方法(代码的最后一部分是其中的一部分)保持运行。

Where do i go wrong in the logic of mutexes and signaling? 互斥锁和信令逻辑在哪里出错? I've already checked that the pthread_cond_t variable is still "alive" before the calling to the cond_wait and the cond_broadcast method, and nothing in that area seems to be the fault. 在调用cond_wait和cond_broadcast方法之前,我已经检查了pthread_cond_t变量是否仍然处于“活动”状态,并且该区域中的任何内容似乎都不是问题。

Despite it's name, pthread_cond_wait is an un conditional wait for a condition. 尽管它的名字, pthread_cond_wait是一个有条件等待的条件。 You must not call pthread_cond_wait unless you have confirmed that there is something to wait for, and the thing it's waiting for must be protected by the associated mutex. 除非已确认有等待的东西,并且您等待的东西必须由关联的互斥锁保护,否则您不得调用pthread_cond_wait

Condition variables are stateless and it is the application's responsibility to store the state of the thing being waited for, called a 'predicate'. 条件变量是无状态的,应用程序有责任存储正在等待的事物的状态,称为“谓词”。

The canonical pattern is: 规范模式是:

pthread_mutex_lock(&mutex);
while(!ready_for_me_to_do_something)
   pthread_cond_wait(&condvar, &mutex);
do_stuff();
ready_for_me_to_do_something=false; // this may or may not be appropriate    
pthread_mutex_unlock(&mutex);

and: 和:

pthread_mutex_lock(&mutex);
ready_for_me_to_do_something=true;
pthread_cond_broadcast(&condvar);
pthread_mutex_unlock(&mutex);

Notice how this code maintains the state in the ready_for_me_to_do_something variable and the waiting thread waits in a loop until that variable is true. 请注意,此代码如何在ready_for_me_to_do_something变量中维护状态,并且等待线程在循环中等待,直到该变量为true。 Notice how the mutex protects that shared variable, and it protects the condition variable (because that is also shared between the threads). 注意互斥锁如何保护该共享变量,以及它如何保护条件变量(因为该变量也在线程之间共享)。

This is not the only correct way to use a condition variable, but it is very easy to run into trouble with any other use. 这不是使用条件变量的唯一正确方法,但是很容易在其他用途​​上遇到麻烦。 You call pthread_cond_wait even if there is no reason to wait. 即使没有理由等待,也可以调用pthread_cond_wait If you wait for your sister to get home with the car before you use it, and she has already returned, you will be waiting a long time. 如果您在使用前等姐姐乘车回家,而她已经回来了,您将等待很长时间。

Your use of pthread_cond_wait() is not correct. 您对pthread_cond_wait()使用不正确。 If a condition variable is signalled while no processes are waiting, the signal has no effect. 如果在没有进程等待的情况下发出条件变量的信号,则该信号无效。 It's not saved for the next time a process waits. 下次进程等待时不会保存。 This means that correct use of pthread_cond_wait() looks like: 这意味着正确使用pthread_cond_wait()如下所示:

pthread_mutex_lock(&mutex);
/* ... */
while (!should_wake_up)
    pthread_cond_wait(&cond, &mutex);

The should_wake_up condition might just be a simple test of a flag variable, or it might be something like a more complicated test for a buffer being empty or full, or something similar. should_wake_up条件可能只是对flag变量的简单测试,或者可能是对缓冲区为空或已满或类似情况的更复杂的测试。 The mutex must be locked to protect against concurrent modifications that might change the result of should_wake_up . 必须锁定互斥锁,以防止可能会更改should_wake_up结果的并发修改。

It is not clear what that test should be in your program - you might need to add a specific flag variable. 目前尚不清楚该测试应该在您的程序中进行-您可能需要添加特定的标志变量。

I don't think there's enough code in the "waking up" part, but my initial guess is that the pthread_cond_wait hasn't been entered at the time pthread_cond_broadcast is issued. 我不认为有足够的代码在“唤醒”的一部分,但我最初的猜测是pthread_cond_wait尚未在当时进入pthread_cond_broadcast发出。

Another possibility is that pthread_cond_wait is in the middle of a spurious wakeup and misses the signal completely. 另一种可能性是pthread_cond_wait处于虚假唤醒中,并且完全错过了信号。

I'm pretty sure that most uses of condition variables also have an external predicate that must be checked after every wakeup to see if there is work to be done. 我很确定,大多数条件变量的使用还具有外部谓词,每次唤醒后都必须检查该谓词,以查看是否有工作要做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM