【Linux】消费者与生产者模型!!

本文介绍了Linux环境下使用POSIX信号量实现的生产者与消费者模型。通过信号量解决线程间的同步和互斥问题,避免资源饥饿。生产者负责向链表中添加数据,消费者则负责从中读取。生产者与消费者间的关系是互斥且同步的,信号量在此起到了关键作用,确保数据的一致性和线程的安全运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

POSIX信号量
信号量的类型:sem_t
初始化信号量函数:int sem_init(sem_t* sem,int pthread,unsigned value);
sem:信号量名
pthread:0表示线程间共享,非0表示进程间共享
value:信号量初始值
销毁信号量函数:int sem_destrpy(sem_t* sem);
等待信号量:int sem_wait(sem_t* sem);
发布信号量:int sem_post(sem_t* sem);

生产者与消费者模型

在对临界资源进行加锁的时候可能会产生一个线程不断的生产资源,一个线程却消费资源很慢,或者一个线程消耗资源很快,但是一个线程生产资源很慢。对于这些情况都会造成一些线程的饥饿问题。
生产者和消费者模型是将生产者和消费者平衡,达到生产和消费相对的平衡,这样可以减少线程的饥饿问题。

生产者:向临界资源里面写入数据
消费者:从临界资源里面读出数据

生产者与生产者:互斥关系
消费者与消费者:互斥关系
生产者与消费者:互斥且同步关系

在生产者生产数据达到一定的时候,生产者将阻塞挂起,这时候如果有其他的生产者想要生产数据的时候,必须先申请信号量资源,但是这时候的信号量资源已经饱和,所以只有等待消费者来消费才可以。在生产者之间也可能存在同时访问临界资源,当一个生产者生产到一半的时候,另外一个生产者也来生产,这时候就会产生生产的数据失效的问题。所以在生产者和生产者,消费者与消费者之间需要互斥关系,需要在生产和消费的时候加上互斥锁,这样就可以防止数据失效的存在。

实例:基于链表的生产者消费者模型

#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<stdlib.h>
#include<sys/types.h>

typedef struct Node{
    int value;
    struct Node*next;
}Node;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
sem_t sem_full;
sem_t sem_empty;

void InitList(Node* head){
    head->next = NULL;
}
Node* allocNode(int d){
    Node* tmp = (Node*)malloc(sizeof(Node));
    if(NULL == tmp){
        perror("malloc");
        exit(1);
    }
    tmp->value = d;
    tmp->next = NULL;
    return tmp;
}
void Push(Node* head,int d){
    Node* tmp = allocNode(d);
    if(NULL == head){
        head->next = tmp;
    }
    tmp->next = head->next;
    head->next = tmp;
}
void PopList(Node* head,int *d){
    if(NULL == head->next)
        return ;
    Node* del = head->next;
    head->next = del->next;
    if(NULL != d)
        *d = del->value;
    free(del);
}

void DestroyList(Node* head){
    if(NULL == head->next)
        return ;
    while(head->next){
        PopList(head,NULL);
    }
    free(head);
}

void* ShowList(Node*head){
    while(head->next){
        head = head->next;
        printf("%d  ",head->value);
    }
    printf("\n");
}

void* fun_c(void* arg){
    Node* head = (Node*)arg;
    int i = 0;
    while(1){
        sem_wait(&sem_empty);
        pthread_mutex_lock(&lock);
        Push(head,i);
        printf("Push data: %d tid = %d\n",i,pthread_self());
        sleep(1);
        i++;
        pthread_mutex_unlock(&lock);
        sem_post(&sem_full);
    }
}

void* fun_p(void* arg){
    Node* head = (Node*)arg;
    int i = 0;
    while(1){
        sem_wait(&sem_full);
        pthread_mutex_lock(&lock);
        int d = -1;
        PopList(head,&d);
        printf("Pop data: %d tid = %d\n",d,pthread_self());
        sleep(1);
        pthread_mutex_unlock(&lock);
        sem_post(&sem_empty);
    }
}


int main(){
    pthread_t t1,t2,t3,t4;
    Node head;
    int i = 0;
    InitList(&head);
    sem_init(&sem_empty,0,0);
    sem_init(&sem_full,0,10);
    pthread_create(&t1,NULL,fun_c,(void*)&head);
    pthread_create(&t3,NULL,fun_p,(void*)&head);
    pthread_create(&t4,NULL,fun_c,(void*)&head);
    pthread_create(&t2,NULL,fun_p,(void*)&head);

    pthread_join(t4,NULL);
    pthread_join(t3,NULL);
    pthread_join(t2,NULL);
    pthread_join(t1,NULL);
    DestroyList(&head);
    sem_destroy(&sem_empty);
    sem_destroy(&sem_full);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值