生产者-消费者的问题

生产者-消费者问题是最经典的操作系统同步与互斥相结合的问题。生活中的很多问题,要么是它的变形,要么是它的简化。

本篇博客的实现方法是用linux版本的线程互斥锁+线程信号量来实现该问题。

问题场景:m个生产者,n个消费者,大小为k的缓冲区。

1、互斥保证:对缓冲区的操作是互斥的。用互斥锁(pthread_mutex_t)实现。
2、同步保证:当缓冲区为空时,消费者阻塞;当缓冲区为满时,生产者阻塞。用线程信号量(sem_t)实现。

编程细节:
1、信号量的初始化:缓冲区初始为空,因此生产者的初始信号量值为k,消费者的初始信号量值为0.
2、先获取互斥锁,然后才能获取信号量。否则会造成死锁。
3、生产者、消费者分别需要一个变量idx来记录可以当前自己可处理的位置。
#include <stdio.h>
#include <pthread.h> //多线程、互斥锁所需头文件
#include <semaphore.h> //线程信号量所需头文件

//设置生产者、消费者、缓冲区的个数
#define M 10
#define N 10
#define K 10
#define X 10

//互斥锁
pthread_mutex_t mutex;
//信号量
sem_t pro;
sem_t con;

//缓冲区和生产者、消费者的游标
int buffer[K] = {0};
int pro_idx = 0;
int con_idx = 0;

void *producer(void *)
{
    for(int i=0;i<X;i++)
    {
        sem_wait(&pro);
        pthread_mutex_lock(&mutex);
        
        int tmp = buffer[pro_idx];
        printf("Produce at buffer[%d] : from %d to 1\n", pro_idx, tmp);
        buffer[pro_idx] = 1;
        pro_idx = (pro_idx+1) % K;
    
        pthread_mutex_unlock(&mutex);
        sem_post(&con);
    }
    return NULL;
}

void *consumer(void *)
{
    for(int i=0;i<X;i++)
    {
        sem_wait(&con);
        pthread_mutex_lock(&mutex);
    
        int tmp = buffer[con_idx];
        printf("Consumer at buffer[%d] : from %d to 0\n", con_idx, tmp);
        buffer[con_idx] = 0;
        con_idx = (con_idx+1) % K;
    
        pthread_mutex_unlock(&mutex);
        sem_post(&pro);
    }
    return NULL;
}

int main(int argc, const char * argv[])
{
    //声明线程标识符
    pthread_t producer_thread[M];
    pthread_t consumer_thread[N];
    
    //初始化线程信号量:初始时为缓冲区全空
    sem_init(&pro, 0, K);
    sem_init(&con, 0, 0);
    
    //初始化互斥锁:下面初始化两种方式都可以
    mutex = PTHREAD_MUTEX_INITIALIZER;
    //pthread_mutex_init(&mutex, NULL);
    
    for (int i=0; i<M; i++)
    {
        if (pthread_create(&producer_thread[i], NULL, producer, NULL))
            printf("Producer Thread Cannot Created.\n");
    }
    
    for(int i=0;i<N;i++)
    {
        if(pthread_create(&consumer_thread[i], NULL, consumer, NULL))
            printf("Consumer Thread Cannot Created.\n");
    }
    
    for(int i=0;i<M;i++)
        pthread_join(producer_thread[i], NULL);
    for(int i=0;i<N;i++)
        pthread_join(consumer_thread[i], NULL);
    
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值