生产者-消费者问题

  1. 互斥锁+信号量:
/*
	生产者生产,消费者消费,容器用单向链表实现
	容器为空,则消费者必须等到生产者生产才能消费
	容器满了,则生产者必须等到消费者消耗才能生产
*/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>

pthread_mutex_t mutex; // 创建一个互斥量
sem_t psem, csem; // 创建两个信号量

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

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

void * producer(void * arg) {
    // 不断的创建新的节点,添加到链表中
    while(1) {
        sem_wait(&psem); // 如果为0,代表容器满了,就不能生产了,需要阻塞直到消费者消耗,才能接着生产

        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_mutex_unlock(&mutex);

        sem_post(&csem); // 每生产一个,就告诉消费者又可以消费1个
    }

    return NULL;
}

void * customer(void * arg) {
    while(1) {
        sem_wait(&csem); // 若容器为空,就阻塞直到不为空才-1

        pthread_mutex_lock(&mutex);
        struct Node * tmp = head;
        head = head->next;
        printf("del node, num : %d, tid : %ld\n", tmp->num, pthread_self());
        free(tmp);
        pthread_mutex_unlock(&mutex);

        sem_post(&psem); // 每消费了一个,就告诉生产者多生产一个补上
    }

    return  NULL;
}

int main() {
    // 创建互斥锁, 信号量
    pthread_mutex_init(&mutex, NULL); 
    sem_init(&psem, 0, 8);// 8可以认为是容器的大小
    sem_init(&csem, 0, 0);

    // 创建5个生产者线程,和5个消费者线程
    pthread_t ptids[5], ctids[5];
    for(int i = 0; i < 5; i++) {
        pthread_create(&ptids[i], NULL, producer, NULL);
        pthread_create(&ctids[i], NULL, customer, NULL);
    }

    // 回收子线程资源, pthread_join是阻塞的
    for(int i = 0; i < 5; i++) {
        pthread_join(ptids[i], NULL);
        pthread_join(ctids[i], NULL);
    }

    // 销毁互斥锁, 信号量
    pthread_mutex_destroy(&mutex);
    sem_destroy(&psem);
    sem_destroy(&csem);

    // 退出主线程
    pthread_exit(NULL);

    return 0;
}
  1. 互斥锁+条件变量
/*
	当容器满的时候,生产者不能生产这个功能没有实现,如果生产者线程抢到调度的次数更多,回导致已知生产
*/
#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);
    }

    return NULL;
}

void * customer(void * arg) {
    while(1) {
        pthread_mutex_lock(&mutex);
        
        struct Node * tmp = head; // 保存头结点的指针
        if(head) { // 容器不为空
            
            head = head->next;
            printf("del node, num : %d, tid : %ld\n", tmp->num, pthread_self());
            free(tmp);
            pthread_mutex_unlock(&mutex);
        } else {
            // 容器为空,需要等待
            // 当这个函数调用阻塞的时候,会释放互斥锁mutex,等到不阻塞了,继续向下执行,会重新加锁。
            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 ptids[5], ctids[5];
    for(int i = 0; i < 5; i++) { 
        pthread_create(&ptids[i], NULL, producer, NULL);
        pthread_create(&ctids[i], NULL, customer, NULL);
    }

    // 回收子线程
    for(int i = 0; i < 5; i++) { 
        pthread_join(ptids[i], NULL);
        pthread_join(ctids[i], NULL);
    }

    // 销毁互斥锁,条件变量
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    pthread_exit(NULL); // 退出主线程

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值