> 文章列表 > 3.13、条件变量

3.13、条件变量

3.13、条件变量

3.13、条件变量

  • 1.条件变量
  • 2.条件变量的常用函数
  • 3.条件变量实现生产者消费者模型(含函数介绍)

1.条件变量

  • 在多线程编程中,条件变量是一种同步机制,常常和锁一起使用。条件变量通常用于线程之间的通信,用于等待和唤醒某个条件的出现。条件变量实际上是一个由系统内核提供的等待队列,线程在这个等待队列上等待条件的出现,而不是忙等待。
  • 条件变量的基本操作有等待和唤醒两种。当线程在等待某个条件的时候,它会阻塞在条件变量上。当有其他线程满足了这个条件并通过条件变量唤醒了该线程时,该线程被唤醒并重新进入运行状态。
  • 在使用条件变量时,需要先获得锁,然后才能对条件变量进行操作。条件变量的等待操作会将锁释放,从而允许其他线程对共享资源进行操作。而唤醒操作则会重新获得锁。

2.条件变量的常用函数

  • 条件变量的类型 pthread_cond_t
  • int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);初始化条件变量
  • int pthread_cond_destroy(pthread_cond_t *cond);销毁条件变量
  • int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);等待条件变量
  • int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);等待进程多时间
  • int pthread_cond_signal(pthread_cond_t *cond);唤醒等待条件变量的线程中的一个线程
  • int pthread_cond_broadcast(pthread_cond_t *cond);唤醒等待条件变量的所有线程

3.条件变量实现生产者消费者模型(含函数介绍)

pthread_cond_wait函数可被多个线程使用

/*条件变量的类型 pthread_cond_tint pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);int pthread_cond_destroy(pthread_cond_t *cond);int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);- 等待,调用了该函数,线程会阻塞。int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);- 等待多长时间,调用了这个函数,线程会阻塞,直到指定的时间结束。int pthread_cond_signal(pthread_cond_t *cond);- 唤醒一个或者多个等待的线程int pthread_cond_broadcast(pthread_cond_t *cond);- 唤醒所有的等待的线程
*/#include <iostream>
#include <pthread.h>
#include <unistd.h>using namespace std;// 定义锁
pthread_mutex_t mutex;
// 定义条件变量
pthread_cond_t cond;struct Node
{int num;Node * next;Node(int _num): num(_num), next(nullptr) {}
};Node * head = nullptr;void * producer(void * arg)
{while (1){// 加锁pthread_mutex_lock(&mutex);Node * newNode = new Node(rand() % 1000);newNode->next = head;head = newNode;printf("add: %d, tid: %ld\\n", newNode->num, pthread_self());// 告诉他们别的线程可以不用阻塞了pthread_cond_signal(&cond);// 解锁pthread_mutex_unlock(&mutex);usleep(100);}pthread_exit(NULL);
}void * customer(void * arg)
{while (1){// 加锁pthread_mutex_lock(&mutex);if (head == nullptr){// 如果为空,阻塞住进程// 阻塞的时候会将mutex解锁,收到信号之后又会加锁,并且不阻塞pthread_cond_wait(&cond, &mutex);pthread_mutex_unlock(&mutex);continue;}Node * tmp = head;head = head->next;printf ("del: %d, tid: %ld\\n", tmp->num, pthread_self());delete tmp;tmp = nullptr;// 解锁pthread_mutex_unlock(&mutex);usleep(100);}pthread_exit(NULL);
}int main()
{// 初始化锁和条件变量pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);// 创建线程pthread_t ptid[5], ctid[5];for (int i = 0; i < 5; i ++ ){// pthread_create(&ptid[i], &attr, producer, NULL);// pthread_create(&ctid[i], &attr, customer, NULL);pthread_create(&ptid[i], NULL, producer, NULL);pthread_create(&ctid[i], NULL, customer, NULL);}// 设置线程分离for (int i = 0; i < 5; i ++ ){pthread_detach(ptid[i]);pthread_detach(ctid[i]);}// 设置while (1){sleep(1);}// 释放释放锁和条件变量pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);// 退出主线程pthread_exit(NULL);return 0;
}