3.13、条件变量

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_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);
        - 唤醒所有的等待的线程
*/

#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;
}

猜你喜欢

转载自blog.csdn.net/z2812470857/article/details/130117666