Linux多线程13-条件变量

上节代码存在的问题:

生产者已经没有数据了, 消费者还在while循环判断是否有数据,浪费资源

没有数据了应该通知生产者生产,生产好了通知消费者消费

这就需要条件变量 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 <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

//创建互斥量
pthread_mutex_t mutex;
//创建条件变量
pthread_cond_t cond;

struct Node{
    int num;
    struct Node* next;
};

//头节点
struct Node* head = NULL;

void* producer(void* arg){
    //往容器中添加内容
    //不断的创建新节点, 添加到链表中
    while(1){
        pthread_mutex_lock(&mutex);
        struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
        newNode -> next = head;
        head = newNode;
        newNode -> num = rand()%1000;
        printf("add node, num: %d, tid: %ld\n", newNode->num, pthread_self());

        //只要生产一个就通知消费者来消费
        pthread_cond_signal(&cond);
        
        pthread_mutex_unlock(&mutex);
        usleep(100);
    }
    return NULL;
}
void* customer(void* arg){
    //从容器中消费内容
    while(1){
        pthread_mutex_lock(&mutex);
        //保存头节点指针
        struct Node* tmp = head;
        
        //判断是否还有数据
        if(head!=NULL){
            head = head->next;
            printf("delete node, num: %d, tid: %ld\n", tmp->num, pthread_self());
            free(tmp);
            pthread_mutex_unlock(&mutex);
            usleep(100);
        }else{
            //没有数据,等待
            //当这个函数调用阻塞的时候, 会对互斥锁进行解锁, 
            //当不阻塞的时候,继续向下执行会重新加锁
            pthread_cond_wait(&cond, &mutex);
            //防止死锁
            pthread_mutex_unlock(&mutex);
        }
    }
    return NULL;
}


int main(){
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    //5个生产者线程, 5个消费者线程
    pthread_t ptid[5], ctid[5];

    int i;
    for(i=0; i<5; i++){
        pthread_create(&ptid[i], NULL, producer, NULL);
        pthread_create(&ctid[i], NULL, customer, NULL);
    }

    for(i=0; i<5; i++){
        pthread_detach(ptid[i]);
        pthread_detach(ctid[i]);
    }

    while(1){
        sleep(10);
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    pthread_exit(NULL);

    return 0;
}

posted @ 2023-06-26 08:59  言叶以上  阅读(7)  评论(0编辑  收藏  举报