如何避免等待已经发送信号的pthread_cond_t

时间:2017-07-27 10:14:30

标签: c++ c pthreads

我在动态库中有一个逻辑,它运行主可执行文件请求的一些服务。

从库代码调用start_service后,在准备好服务之前需要做一些准备工作,在此期间,主代码不应尝试访问服务。

要在服务准备就绪时通知主代码,我使用条件变量并发出主可执行文件的信号。

在主代码等待条件变量之前,我想听听一些关于在库变得可用时处理情况的最佳方法的建议。在这种情况下,等待可以永远持续......

这是服务代码:

extern pthread_cond_t cnd;
extern pthread_mutex_t mtx;

void start_service()
{
   // getting serviceable.       
   pthread_cond_signal(&cnd);
   main_loop(); 
}

这是主要代码。

pthread_cond_t cnd;
pthread_mutex_t mtx;

int main() 
{    
    pthread_cond_init(&cnd,NULL);
    pthread_mutex_init(&mtx, NULL);

    std::thread mytrd(&start_service);
    ...
    pthread_mutex_lock(&mtx);

    pthread_cond_wait(&cnd, &mtx);  // what happens if we get here after the signal already sent. 
    pthread_mutex_unlock(&mtx);
    ...
}

P.S期望的行为应该是主代码避免等待条件变量已经发出信号。

2 个答案:

答案 0 :(得分:2)

您需要一个谓词并将wait括在谓词检查中:

    pthread_mutex_lock(&mtx);
    while( ! predicate ) pthread_cond_wait(&cnd, &mtx);  
    pthread_mutex_unlock(&mtx);

通过这种方式,线程不会在不需要时开始等待事件。 你需要这个的第二个原因是为了避免可能发生的虚假唤醒,即使另一个线程没有发出信号,pthread_cond_wait可能会返回。

然后另一个线程必须执行(您需要锁定互斥锁以保护谓词):

 pthread_lock_mutex(&mtx);
 predicate = true;  
 pthread_cond_signal(&cnd);
 pthread_unlock_mutex(&mtx);

答案 1 :(得分:2)

您可以使用初始计数为0的信号量,因此main会被阻止,直到start_service()将信号量计数增加到1。如果在阻止调用main之前{1}},start_service()将信号量计数增加到1,main将永远不会进入等待状态。如下所示。

void start_service()
{
    // getting serviceable.       
    sem_post(&sem_mutex);//increases to 1
    main_loop(); 
}
int main() 
{  
    sem_init(&sem_mutex, 0, 0);//initially blocked.
    std::thread mytrd(&start_service);
    sem_wait(&sem_mutex);
    ...
}