pthread_cond_wait() 函数的使用

时间:2022-01-15 08:27:08

1. 首先pthread_cond_wait 的定义是这样的

The pthread_cond_wait() and pthread_cond_timedwait() functions are used to block on a condition variable. They are called with mutex locked by the calling thread or undefined behaviour will result.

These functions atomically release mutex and cause the calling thread to block on the condition variablecond; atomically here means "atomically with respect to access by another thread to the mutex and then the condition variable". That is, if another thread is able to acquire the mutex after the about-to-block thread has released it, then a subsequent call to pthread_cond_signal() or pthread_cond_broadcast() in that thread behaves as if it were issued after the about-to-block thread has blocked.

2. 由上解释可以看出,pthread_cond_wait() 必须与pthread_mutex 配套使用。

pthread_cond_wait()函数一进入wait状态就会自动release mutex.

In Thread1:

pthread_mutex_lock(&m_mutex);   
pthread_cond_wait(&m_cond,&m_mutex);   
pthread_mutex_unlock(&m_mutex);

In Thread2:

pthread_mutex_lock(&m_mutex);   
pthread_cond_signal(&m_cond);   
pthread_mutex_unlock(&m_mutex);

为什么要与pthread_mutex 一起使用呢? 这是为了应对 线程1在调用pthread_cond_wait()但线程1还没有进入wait cond的状态的时候,此时线程2调用了 cond_singal 的情况。 如果不用mutex锁的话,这个cond_singal就丢失了。加了锁的情况是,线程2必须等到 mutex 被释放(也就是 pthread_cod_wait() 进入wait_cond状态 并自动释放mutex) 的时候才能调用cond_singal.

3.

pthread_cond_wait() 一旦wait成功获得cond 条件的时候会自动 lock mutex.

这就会出现另一个问题。这是因为

The pthread_cond_wait() and pthread_cond_timedwait()  is a cancellation point.

In Thread3:

pthread_cancel(&m_thread);

pthread_join();

因为pthread_cond_wait() and pthread_cond_timedwait()  是线程退出点函数,因此在Thread3中

可以调用pthread_cancel()来退出线程1。那样显然线程1会在pthread_cond_wait(&m_cond,&m_mutex);   和 pthread_mutex_unlock(&m_mutex); 之间退出,    pthread_cond_wait() 函数返回后自动lock住了mutex, 这个时候线程1退出(并没有运行到pthread_mutex_unlock()),如果Thread2这个时候就再也得不到lock状态了。

通常解决这个问题的办法如下

void cleanup(void *arg)
{
  pthread_mutex_unlock(&mutex);
}
void* thread1(void* arg)
{
  pthread_cleanup_push(cleanup, NULL);  // thread cleanup handler
  pthread_mutex_lock(&mutex);
  pthread_cond_wait(&cond, &mutex);
  pthread_mutex_unlock(&mutex);
  pthread_cleanup_pop(0);
}