条件变量

Posted on 2023-02-23 20:00  lyc2002  阅读(25)  评论(0编辑  收藏  举报

介绍

#include <pthread.h>
pthread_cond_t cond;

int pthread_cond_init(pthread_cond_t *restrict cond,
                      const pthread_condattr_t *restrict attr);
     
int pthread_cond_destroy(pthread_cond_t *cond);

功能:初始化/销毁条件变量

参数:

  • cond:条件变量的地址
  • attr:条件变量属性,一般使用默认属性,指定为 NULL

返回值:

  • 成功返回 0
  • 失败返回错误号
#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *restrict cond,
                      pthread_mutex_t *restrict mutex);

功能:阻塞调用该函数的线程

  • pthread_cond_wait 在阻塞线程中,如果已经对互斥锁上锁,为避免死锁会把锁打开
  • 当线程解除阻塞的时候,函数内部会帮助这个线程再次将互斥锁锁上,继续向下访问临界区

参数:

  • cond:条件变量的地址
  • mutex:互斥锁的地址

返回值:

  • 成功返回 0
  • 失败返回错误号
#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond); // 唤醒至少一个

int pthread_cond_broadcast(pthread_cond_t *cond); // 唤醒所有

功能:唤醒阻塞在条件变量上的线程

参数:

  • cond:条件变量的地址

返回值:

  • 成功返回 0
  • 失败返回错误号

简单使用

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

#define N 30

pthread_mutex_t mutex;
pthread_cond_t empty, full;

int buf[N], idx = -1;

void * producer(void *arg)
{
    while (1) {
        pthread_mutex_lock(&mutex);
        while (idx == N - 1) {
            pthread_cond_wait(&empty, &mutex);
        }
        buf[++idx] = 1;
        printf("producer offer %d\n", idx);
        pthread_cond_signal(&full);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    
    pthread_exit(NULL);
}

void * consumer(void *arg)
{
    while (1) {
        pthread_mutex_lock(&mutex);
        while (idx == -1) {
            pthread_cond_wait(&full, &mutex);
        }
        printf("consumer get %d\n", idx);
        buf[idx--] = 0;
        pthread_cond_signal(&empty);
        pthread_mutex_unlock(&mutex);
        sleep(3);
    }
    
    pthread_exit(NULL);
}

int main()
{
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&empty, NULL);
    pthread_cond_init(&full, NULL);
    
    pthread_t t1[5], t2[5];
    for (int i = 0; i < 5; i++) {
        pthread_create(&t1[i], NULL, producer, NULL);
        pthread_create(&t2[i], NULL, consumer, NULL);
    }
    for (int i = 0; i < 5; i++) {
        pthread_join(t1[i], NULL);
        pthread_join(t2[i], NULL);
    }
    
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&empty);
    pthread_cond_destroy(&full);
    
    return 0;
}

注意事项

  • pthread_cond_signal 要放在 unlock 之前
  • 要使用两个条件变量。如果只使用一个且搭配 pthread_cond_signal(),会导致消费者线程唤醒消费者线程,导致生产者线程无限阻塞