C语言模拟生产者-消费者问题

依然是OS课程实验,在这里写一篇blog记录一下。

0x00 实验目的

探索、理解并掌握操作系统命令解释器的设计原理和实现机制,基于 Linux 内核进行相 应命令解释程序的设计和实现,并在 Linux 操作系统平台上加以测试验证。

0x01 实验环境

系统环境:MAC OS Catalina 10.15.3
虚拟机环境:Parallels desktop 15+Ubuntu 18.04.3 LTS
编程语言:C语言

0x02运行环境

理论上可以在Linux的各个发行版中运行

0x03实现代码

生产者消费者问题还是比较简单的,主要用到了C语言的信号量和线程同步机制。代码注释比较详细,在这里不过多解释,直接给出代码。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define THREAD_NUM 3  //生产者消费者数量
#define BUF_NUM 8  //缓存区大小

int in = 0;   // 生产在者指针
int out = 0; // 消费者指针
int buf[BUF_NUM] = { 0 };  // 缓冲区
sem_t empty; // 空缓存区信号量
sem_t full;   // 满缓存区信号量
pthread_mutex_t mutexP; // 生产者互斥信号量
pthread_mutex_t mutexC; // 消费者互斥信号量

void *product(void *args)
{
    int i=5;  //每个生产者生产5个产品
    int *id=(int*)args;

    while(i)
    {
        sem_wait(&empty);  //等待空信号量
        pthread_mutex_lock(&mutexP);  //等待生产者互斥信号量
        buf[in]=1;  //生产数据放入缓存区,这里用1指代
        printf("生产者%d:生产数据放入缓存区%d中!\n",*id,in);
        in=(in+1)%BUF_NUM;  //指针前进
        pthread_mutex_unlock(&mutexP);  //释放生产者互斥信号量
        sem_post(&full);  //释放满缓存区信号量
        i--;
    }

}

void *customer(void *args)
{
    int i=5;  //每个消费者者消费5个产品
    int *id=(int*)args;

    while(i)
    {
        sem_wait(&full);  //等待满信号量
        pthread_mutex_lock(&mutexC);  //等待消费者互斥信号量
        buf[out]=0;  //消费数据移出缓存区,这里用0指代
        printf("消费者%d:消费数据从缓存区%d中!\n",*id,out);
        out=(out+1)%BUF_NUM;  //指针前进
        pthread_mutex_unlock(&mutexC);  //释放消费者互斥信号量
        sem_post(&empty);  //释放空缓存区信号量
        i--;
    }

}

int main()
{
    pthread_t Ptid[THREAD_NUM];  //生产者标识
    pthread_t Ctid[THREAD_NUM];  //消费者标识
    int id[THREAD_NUM]={1,2,3};  //生产者消费者编号
    int ret[THREAD_NUM];
    //初始化信号量
    sem_init(&empty, 0, BUF_NUM);
    sem_init(&full, 0, 0);
    //初始化互斥信号量
    pthread_mutex_init(&mutexP, NULL);
    pthread_mutex_init(&mutexC, NULL);

    for(int i=0;i<THREAD_NUM;i++)
    {
        ret[i]=pthread_create(&Ptid[i], NULL, product, (void*)&id[i]);
        if (ret[i] != 0)
        {
            printf("生产者%d号线程创建失败! \n", i+1);
            exit(0);
        }
    }

    for(int i=0;i<THREAD_NUM;i++)
    {
        ret[i]=pthread_create(&Ctid[i], NULL, customer, (void*)&id[i]);
        if (ret[i] != 0)
        {
            printf("消费者%d号线程创建失败! \n", i+1);
            exit(0);
        }
    }

    for(int i=0;i<THREAD_NUM;i++)
    {
        pthread_join(Ptid[i],NULL);
        pthread_join(Ctid[i],NULL);
    }
    return 0;
}

0x04 测试结果

下面是当程序运行起来后显示的内容:
执行结果
从上图可以看出,当程序运行时,首先生产者1开始生产数据并放在缓存区0中,然后是生产者3开始生产,之后消费者2会首先从缓存区0中取出数据,然后后面继续生产和消费,逻辑成立,程序没有问题,实现了生产者和消费者多线程运行的功能!

0x05 后记

之前写多线程大都是用的python和java,倒是的确没有用C语言写过,这次写这个程序,也事先查阅了一些关于C语言多线程和信号量的资料,毕竟C语言还是更接近底层的语言,多学一些总没坏处。程序逻辑还是比较简单的,只不过多线程调试起来比较费力,不过总体情况还可以,过几天把哲学家就餐问题和读者优先/写者优先的读者写者问题也写一下吧。

源码已上传GitHub:源代码

END
本文作者:
文章标题:C语言模拟生产者-消费者问题
本文地址:http://hackerhome.top/index.php/archives/7/
版权说明:若无注明,本文皆由"岁月年华的秘密基地"原创,转载请保留文章出处。
最后修改:2021 年 02 月 13 日 12 : 51 AM
如果觉得我的文章对你有用,请随意赞赏