【问题标题】:How to avoid waiting for pthread_cond_t where signal already sent如何避免等待已发送信号的 pthread_cond_t
【发布时间】:2018-01-03 00:09:58
【问题描述】:

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

从库代码调用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 期望的行为应该是主代码避免等待条件变量(如果它已经发出信号)。

【问题讨论】:

  • 您可以使用初始计数为0 的信号量,因此main 被阻塞,直到start_service() 将信号量计数增加到1。如果在main 中的块调用之前,start_service() 增加信号量计数为1,main 永远不会进入等待状态。
  • 嗨,感谢您的评论,这似乎是一种合适的方式..也许您可以修改我的代码来表达您的想法?
  • pthread_wait 必须始终在循环中使用,它具有等待的条件。不使用循环是不好的做法,随时可能失败。

标签: c++ c pthreads


【解决方案1】:

您需要一个谓词并将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);

【讨论】:

  • 谓词应该是全局变量,就像mtx和cnd一样,对吧?
  • @Zohar81:是的。但更好的是,将这些东西打包成一个结构,并将其作为参数传递给线程。这样可以避免全局变量,并且可以拥有更多的服务。
  • @Zohar81 如果你可以访问 C++11,你应该使用<thread>,如果你没有,那么<boost/thread>。至少你应该使用一个作用域锁,它在其构造函数中执行pthread_mutex_lock,在析构函数中执行pthread_mutex_unlock。这样你就不会忘记解锁它(或在异常情况下错过锁定它)
【解决方案2】:

您可以使用初始计数为0 的信号量,因此main 被阻塞,直到start_service() 将信号量计数增加到1。如果在main 中的块调用之前,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);
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 2023-02-15
    • 1970-01-01
    • 2022-01-21
    • 2021-06-21
    相关资源
    最近更新 更多