POSIX条件变量pthread_cond Linux线程同步之条件变量pthread_cond_t

1.什么是条件变量

  条件变量是维持线程同步的一种手段,当条件不满足时,线程会被自动阻塞,直到条件被触发为止。

  条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包含两个动作:1.一个或多个线程等待条件变量满足而被挂起;2.一个线程使条件成立(发出条件成立信号唤醒被阻塞的一个或多个线程)。

2.条件变量通常与互斥锁配合使用,为什么?互斥锁保护的是什么?

先来看一个条件变量的使用场景:

等待条件变量函数原型:

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
void *func(void *arg)
{
    pthread_mutex_lock(&mutex);
    while(cond_is_false) //条件不满足,wait
    {
        pthread_cond_wait(&cond, &mutex);
    }
    //...
    pthread_mutex_unlock(&mutex);
    return (void *)0;
}

mutex保护的是什么?

  不是条件变量本身cond,而是确定条件变量是否成立的线程间共享的全局变量,当mutex被lock后,可以放心的去判断全局变量,而不用担心在这期间被其他线程改变其状态。当条件不满足时,该线程首先unlock了mutex,线程被挂起(以上两步操作在pthread_cond_wait中完成,两步操作一块完成(保证原子性)),当mutex被unlock后,其他线程就有机会修改全局变量使条件变量满足,从而发送条件成立信号,调用pthread_cond_signal,唤醒在pthread_cond_wait中仍在被阻塞的线程,使其从pthread_cond_wait中返回,在返回前需要再次lock mutex。

pthread_cond_wait的工作流程可总结为:

  1.unlock mutex;

  2.waiting;

  3.条件满足时lock mutex返回。1和2在一起完成时原子性的。

3.为什么使用while而不是if?

  1. 因为pthread_cond_wait函数返回并不意味着一定是条件满足(被其他线程的pthread_cond_signal唤醒),而有可能是意外返回。
  2. 【个人理解,不一定正确】在某线程A发送条件满足信号调用pthread_cond_signal、unlock mutex后,到从waiting中唤醒的线程B lock mutex之间,可能会有其他线程C先一步lock mutex而导致条件变量不满足。因此等到被唤醒的线程B lock mutex后需再次判断条件是否真的满足。

4.为什么unlock与wait操作要在原子操作内进行?

  如果不是原子操作,先unlock mutex,再wait(在wait时条件成立可被唤醒)。如果发生以下情况:在unlock之后,wait之前,有其他线程获取到mutex,使条件变量满足,并发出signal,而原线程因为还没wait而错过这个信号。

5.条件变量使用规范

等待条件:

pthread_mutex_lock(&mutex);
while(条件为假)
{
    pthread_cond_wait(&cond, &mutex);
}
修改条件
pthread_mutex_unlock(&mutex);

条件满足时唤醒:

pthread_mutex_lock(&mutex);
设置条件为真
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

参考:Linux线程同步之条件变量pthread_cond_t

猜你喜欢

转载自www.cnblogs.com/dabai56/p/11107087.html