线程同步——条件变量

条件变量

在程序中我们通常都会遇到等待某个条件变为真的再进行处理的情况。可以使用轮询的方式不断测试变量,但这样做非常浪费资源。也可以使用信号的机制,测试该变量之后调用 pause 以等待该条件变真。这样处理的问题在于如果测试该条件之后、pause 之前条件变为真,线程永远阻塞。条件变量为我们提供一种很好的解决方法。它必须和互斥量一起使用才可以达到我们想要的效果。它的工作原理说明如下:当我们调用 wait 函数来等待条件变为真时,必须传入一个锁住的互斥量,这样做是为了让其他线程在此线程调用 wait 函数时没有机会更改此条件。然后在 wait 函数中,自动把调用线程放到等待条件的线程列表上。最后将互斥量解锁来等待条件变为真。

接口函数

条件变量使用 pthread_cont_t 数据类型。如果要对其进行使用,必须首先进行初始化。也有静态和动态两种方式。静态方式直接赋值 PTHREAD_COND_INITIALIZER 动态方式需要调用下面的接口函数:

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);

int pthread_cond_destory(pthread_cond_t *cond);

                        两个函数返回值:若成功,返回0;否则,返回错误编号

我们使用下面的 wait 函数来等待条件变为真:

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
                        函数返回值:若成功,返回0;否则,返回错误编号

关于 pthread_cond_wait 函数的原理上面已经解释过了。有一点需要注意:当该函数正确返回时,互斥量再次被锁住,这样做的目的显然是为了防止条件变量再次被修改。

有两个函数可以用于通知线程条件已经满足。 pthread_cond_signal 函数至少能唤醒一个等待该条件的线程,而 pthread_cond_broadcast 函数则能唤醒等待该条件的所有线程。

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
                        两个函数返回值:若成功,返回0;否则,返回错误编号

实例

#include <pthread.h>
#include <stdio.h>


pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;




void *fun1(void *arg)
{
    pthread_mutex_lock(&mutex);    
    if (pthread_cond_wait(&cond, &mutex) == 0)
    {
        printf("Hello world\n");
    }
    
    pthread_mutex_unlock(&mutex);
    pthread_exit((void*)1);
}

void *fun2(void *arg)
{
    pthread_mutex_lock(&mutex);    
    sleep(2);
    pthread_cond_signal(&cond); 
    pthread_mutex_unlock(&mutex);
    pthread_exit((void*)2);
}


int main()
{
    
    pthread_t tid1, tid2;

    if (pthread_create(&tid1, NULL, fun1, NULL) != 0)
        return -1;
    if (pthread_create(&tid2, NULL, fun2, NULL) != 0)
        return -1;
    
    sleep(4);
    return 0;
}

 

你可能感兴趣的:(线程同步——条件变量)