操作系统同步生产者消费者问题


Linux进程创建  

一、设计目的

通过模拟操作者生产者经典问题的实现,深入理解操作系统中多线程同步法的理论知识, 加深对教材中的重要算法的理解。同时通过编程实现这些算法,更好地掌握操作系统的原理及实现方法,提高综合运用各专业课知识的能力。

二、设计要求

初始条件:

1. 操作系统:Linux

2. 程序设计语言:C语言

3. 其中(生产者)从外设获取数据进行生产 

另外(消费者)消费后进行输出,并存储输出结果。

技术要求:

1)为每个生产者/消费者产生一个线程,设计正确的同步算法

2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的当前全部内容、当前指针位置和生产者/消费者线程的自定义标识符。

3)生产者和消费者各30个;

4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。

三、设计说明

一 信号量

PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下:
    P(S):①将信号量S的值减1,即S=S-1;
           ②如果S?0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。
    V(S):①将信号量S的值加1,即S=S+1;
           ②如果S>0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。
PV操作的意义:我们用信号量及PV操作来实现进程的同步和互斥。PV操作属于进程的低级通信。

什么是信号量?信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信 号量的下一个进程。信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进 程个数。注意,信号量的值仅能由PV操作来改变。
     一般来说,信号量S?0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个单位资源,因此S的值减1;当S<0时,表示已经没有可用资 源,请求者必须等待别的进程释放该类资源,它才能运行下去。而执行一个V操作意味着释放一个单位资源,因此S的值加1;若S?0,表示有某些进程正在等待 该资源,因此要唤醒一个等待状态的进程,使之运行下去。

利用信号量和PV操作实现进程互斥的一般模型是:
进程P1              进程P2           ……          进程Pn
……                  ……                           ……
P(S);              P(S);                         P(S);
临界区;             临界区;                        临界区;
V(S);              V(S);                        V(S);
……                  ……            ……           ……

    其中信号量S用于互斥,初值为1。
    使用PV操作实现进程互斥时应该注意的是:
    (1)每个程序中用户实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。若有多个分支,要认真检查其成对性。
    (2)P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。
   (3)互斥信号量的初值一般为1。

利用信号量和PV操作实现进程同步
PV操作是典型的同步机制之一。用一个信号量与一个消息联系起来,当信号量的值为0时,表示期望的消息尚未产生;当信号量的值非0时,表示期望的消息已经存在。用PV操作实现进程同步时,调用P操作测试消息是否到达,调用V操作发送消息。
    使用PV操作实现进程同步时应该注意的是:

(1)分析进程间的制约关系,确定信号量种类。在保持进程间有正确的同步关系情况下,哪个进程先执行,哪些进程后执行,彼此间通过什么资源(信号量)进行协调,从而明确要设置哪些信号量。
    (2)信号量的初值与相应资源的数量有关,也与P、V操作在程序代码中出现的位置有关。
    (3)同一信号量的P、V操作要成对出现,但它们分别在不同的进程代码中。

(3)一组生产者,一组消费者,公用n个环形缓冲区
    在这个问题中,不仅生产者与消费者之间要同步,而且各个生产者之间、各个消费者之间还必须互斥地访问缓冲区。
定义四个信号量:
empty——表示缓冲区是否为空,初值为20。
full——表示缓冲区中是否为满,初值为0。
mutex——生产者之间的互斥信号量,初值为null。

    设缓冲区的编号为1~n-1,定义两个指针in和out,分别是生产者进程和消费者进程使用的指针,指向下一个可用的缓冲区。
生产者进程
do{
     生产一个产品;
     P(empty);
     P(mutex1);
     产品送往buffer(in);
     in=(in+1)mod n;
     V(mutex1);
     V(full);
}while(1)
消费者进程
do{
 P(full)
   P(mutex2);
   从buffer(out)中取出产品;
   out=(out+1)mod n;
   V(mutex2);
   V(empty);
   消费该产品;
   }while(1)
  需要注意的是无论在生产者进程中还是在消费者进程中,两个P操作的次序不能颠倒。应先执行同步信号量的P操作,然后再执行互斥信号量的P操作,否则可能造成进程死锁。

 

3 开发环境与工具

系统平台:LINUX环境

实现语言:C语言

开发工具:VI编辑器

4 概要设计

 程序模块说明

生产者(Producer)模块 

生产者线程向一缓冲区中写入数据,且写入缓冲区的数目不能超过缓冲区容量。当生产者产生出数据,需要将其存入缓冲区之前,首先检查缓冲区中是否有“空”存储单元,若缓冲区存储单元全部用完,则生产者必须阻塞等待,直到消费者取走一个存储单元的数据,唤醒它。若缓冲区内有“空”存储单元,生产者需要判断此时是否有别的生产者或消费者正在使用缓冲区,若是有,则阻塞等待,否则,获得缓冲区的使用权,将数据存入缓冲区,释放缓冲区的使用权。

消费者(Consumer)模块 

消费者线程从缓冲区中读取数据,且消费者读取的数目不能超过生产者写入的数目。消费者取数据之前,首先检查缓冲区中是否存在装有数据的存储单元,若缓冲区为“空”,则阻塞等待,否则,判断缓冲区是否正在被使用,若正被使用,若正被使用,则阻塞等待,否则,获得缓冲区的使用权,进入缓冲区取数据,释放缓冲区的使用权。

 

 

四、运行结果及分析

 

 

 

五、总结

用多线程同步互斥方法解决生产者-消费者问题 

本次课程设计, 在做的过程中,我体会到了自己的不足,很多地方都不懂,但是我觉得在这个阶段对一些比较深的东西也不一定要处处都弄懂,有时候子要自己跟着做,会用,久而久之也会随着经验的加深而慢慢弄懂,这虽然是一种不求甚解的态度,但在初级编程中往往是很有用的。  本次课程设计的程序更具要求定义了20个缓冲区,基本上能顺利解决生产者消费者问题,但也存在很多不足之处。因为程序都是根据别人的来

 

 

 源程序代码

 

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h> //POSIX API
#define BUFFER_SIZE 20//20个缓冲区
#define MES 30 //每个生产者生产的30个消息
int consumenum = 0;
int buffer[20]= {0};
sem_t empty;//表示缓冲区是否为空,初值为20
sem_t full;//表示缓冲区中是否为满,初值为0
pthread_mutex_t  mutex; //for mutual exclusion进程信号量
int in=0;               //point to the next free positon
int out=0;      //point to the first full positon
//把所有的缓冲区输出到屏幕上
void printAll()
{
    int i;
    for(i=0; i<20; i++)
        printf("%d ",buffer[i]);
    printf("\n");
    printf("current producer pointer:%d\n",in);
    printf("current consumer pointer:%d\n",out);
}
//生产者线程 1
void producer1(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 2
void producer2(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 3
void producer3(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 4
void producer4(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 5
void producer5(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 6
void producer6(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 7
void producer7(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 8
void producer8(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 9
void producer9(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 10
void producer10(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 11
void producer11(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 12
void producer12(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 13
void producer13(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 14
void producer14(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 15
void producer15(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 16
void producer16(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 17
void producer17(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 18
void producer18(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 19
void producer19(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 20
void producer20(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 21
void producer21(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 22
void producer22(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 23
void producer23(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 24
void producer24(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 25
void producer25(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 26
void producer26(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 27
void producer27(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 28
void producer28(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 29
void producer29(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count > MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}
//生产者线程 30
void producer30(char *arg)
{
    int count = 0;
    do
    {
        sem_wait(&empty);    //空缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁
        //往Buffer中放入产品
        ++count;
        if(count >= MES) break;
        buffer[in]=in+1;
        in=(in+1)%BUFFER_SIZE;//放入指针调整,为下次送出做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex); //信号量解锁
        sem_post(&full);      //满缓冲区加1,即当公共资源增加时,调用函数sem_post()增加信号量
        sleep(1);
    }
    while(count <= MES);
}

//消费者线程 1
void consumer1(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        buffer[out]=0;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 2
void consumer2(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 3
void consumer3(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 4
void consumer4(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 5
void consumer5(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 6
void consumer6(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 7
void consumer7(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 8
void consumer8(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 9
void consumer9(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 10
void consumer10(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 11
void consumer11(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 12
void consumer12(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 13
void consumer13(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 14
void consumer14(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 15
void consumer15(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 16
void consumer16(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 17
void consumer17(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 18
void consumer18(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 19
void consumer19(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 20
void consumer20(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 21
void consumer21(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 22
void consumer22(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 23
void consumer23(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 24
void consumer24(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 25
void consumer25(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 26
void consumer26(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
        ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 27
void consumer27(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 28
void consumer28(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 29
void consumer29(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//消费者线程 30
void consumer30(char *arg)
{
    do
    {
        sem_wait(&full);  //满缓冲区减1
        pthread_mutex_lock(&mutex);  //信号量上锁//从Buffer中取出产品
        buffer[out]=0;
         ++consumenum;
        if(consumenum >= MES * 30) goto loop;
        out=(out+1)%BUFFER_SIZE;//取指针调整,为下次取做准备
        printf("%s\n",arg);
        printAll();
        pthread_mutex_unlock(&mutex);  //信号量解锁
        sem_post(&empty);  //空缓冲区加1
        sleep(2);
    }
    while(1);
    loop: exit(0);
}
//主线程
int main()
{
    //创建进程
    pthread_t producer_1,producer_2,producer_3,producer_4,producer_5,producer_6,producer_7,producer_8,producer_9,producer_10,producer_11,producer_12,producer_13,producer_14,producer_15,producer_16,producer_17,producer_18,producer_19,producer_20,producer_21,producer_22,producer_23,producer_24,producer_25,producer_26,producer_27,producer_28,producer_29,producer_30;
    pthread_t consumer_1,consumer_2,consumer_3,consumer_4,consumer_5,consumer_6,consumer_7,consumer_8,consumer_9,consumer_10,consumer_11,consumer_12,consumer_13,consumer_14,consumer_15,consumer_16,consumer_17,consumer_18,consumer_19,consumer_20,consumer_21,consumer_22,consumer_23,consumer_24,consumer_25,consumer_26,consumer_27,consumer_28,consumer_29,consumer_30;
    void *retval;
    pthread_mutex_init(&mutex,NULL);// /* 用默认属性初始化一个互斥变量mutex// 初始化信号量
    sem_init(&full,0,0);
    sem_init(&empty,0,BUFFER_SIZE);
    //pthread_create函数用来创建生产者和消费者进程,其四个参数分别表示为进程、NULL、进程要执行的函数、执行函数时的参数
    pthread_create(&producer_1,NULL,(void*)producer1,"producer1:");
    pthread_create(&consumer_1,NULL,(void*)consumer1,"consumer1:");
    pthread_create(&producer_2,NULL,(void*)producer2,"producer2:");
    pthread_create(&consumer_2,NULL,(void*)consumer2,"consumer2:");
    pthread_create(&producer_3,NULL,(void*)producer3,"producer3:");
    pthread_create(&consumer_3,NULL,(void*)consumer3,"consumer3:");
    pthread_create(&producer_4,NULL,(void*)producer4,"producer4:");
    pthread_create(&consumer_4,NULL,(void*)consumer4,"consumer4:");
    pthread_create(&producer_5,NULL,(void*)producer5,"producer5:");
    pthread_create(&consumer_5,NULL,(void*)consumer5,"consumer5:");
    pthread_create(&producer_6,NULL,(void*)producer6,"producer6:");
    pthread_create(&consumer_6,NULL,(void*)consumer6,"consumer6:");
    pthread_create(&producer_7,NULL,(void*)producer7,"producer7:");
    pthread_create(&consumer_7,NULL,(void*)consumer7,"consumer7:");
    pthread_create(&producer_8,NULL,(void*)producer8,"producer8:");
    pthread_create(&consumer_8,NULL,(void*)consumer8,"consumer8:");
    pthread_create(&producer_9,NULL,(void*)producer9,"producer9:");
    pthread_create(&consumer_9,NULL,(void*)consumer9,"consumer9:");
    pthread_create(&producer_10,NULL,(void*)producer10,"producer10:");
    pthread_create(&consumer_10,NULL,(void*)consumer10,"consumer10:");
    pthread_create(&producer_11,NULL,(void*)producer11,"producer11:");
    pthread_create(&consumer_11,NULL,(void*)consumer11,"consumer11:");
    pthread_create(&producer_12,NULL,(void*)producer12,"producer12:");
    pthread_create(&consumer_12,NULL,(void*)consumer12,"consumer12:");
    pthread_create(&producer_13,NULL,(void*)producer13,"producer13:");
    pthread_create(&consumer_13,NULL,(void*)consumer13,"consumer13:");
    pthread_create(&producer_14,NULL,(void*)producer14,"producer14:");
    pthread_create(&consumer_14,NULL,(void*)consumer14,"consumer14:");
    pthread_create(&producer_15,NULL,(void*)producer15,"producer15:");
    pthread_create(&consumer_15,NULL,(void*)consumer15,"consumer15:");
    pthread_create(&producer_16,NULL,(void*)producer16,"producer16:");
    pthread_create(&consumer_16,NULL,(void*)consumer16,"consumer16:");
    pthread_create(&producer_17,NULL,(void*)producer17,"producer17:");
    pthread_create(&consumer_17,NULL,(void*)consumer17,"consumer17:");
    pthread_create(&producer_18,NULL,(void*)producer18,"producer18:");
    pthread_create(&consumer_18,NULL,(void*)consumer18,"consumer18:");
    pthread_create(&producer_19,NULL,(void*)producer19,"producer19:");
    pthread_create(&consumer_19,NULL,(void*)consumer19,"consumer19:");
    pthread_create(&producer_20,NULL,(void*)producer20,"producer20:");
    pthread_create(&consumer_20,NULL,(void*)consumer20,"consumer20:");
    pthread_create(&producer_21,NULL,(void*)producer21,"producer21:");
    pthread_create(&consumer_21,NULL,(void*)consumer21,"consumer21:");
    pthread_create(&producer_22,NULL,(void*)producer22,"producer22:");
    pthread_create(&consumer_22,NULL,(void*)consumer22,"consumer22:");
    pthread_create(&producer_23,NULL,(void*)producer23,"producer23:");
    pthread_create(&consumer_23,NULL,(void*)consumer23,"consumer23:");
    pthread_create(&producer_24,NULL,(void*)producer24,"producer24:");
    pthread_create(&consumer_24,NULL,(void*)consumer24,"consumer24:");
    pthread_create(&producer_25,NULL,(void*)producer25,"producer25:");
    pthread_create(&consumer_25,NULL,(void*)consumer25,"consumer25:");
    pthread_create(&producer_26,NULL,(void*)producer26,"producer26:");
    pthread_create(&consumer_26,NULL,(void*)consumer26,"consumer26:");
    pthread_create(&producer_27,NULL,(void*)producer27,"producer27:");
    pthread_create(&consumer_27,NULL,(void*)consumer27,"consumer27:");
    pthread_create(&producer_28,NULL,(void*)producer28,"producer28:");
    pthread_create(&consumer_28,NULL,(void*)consumer28,"consumer28:");
    pthread_create(&producer_29,NULL,(void*)producer29,"producer29:");
    pthread_create(&consumer_29,NULL,(void*)consumer29,"consumer29:");
    pthread_create(&producer_30,NULL,(void*)producer30,"producer30:");
    pthread_create(&consumer_30,NULL,(void*)consumer30,"consumer30:");
   //pthread_join用来表示等待线程的结束,表示producer1,producer2,producer3, producer4, consumer1,consumer2,consumer3 consumer4执行完毕之前主程序必须等待
    pthread_join(producer_1, &retval);
    pthread_join(consumer_1, &retval);
    pthread_join(producer_2, &retval);
    pthread_join(consumer_2, &retval);
    pthread_join(producer_3, &retval);
    pthread_join(consumer_3, &retval);
    pthread_join(producer_4, &retval);
    pthread_join(consumer_4, &retval);
    pthread_join(producer_5, &retval);
    pthread_join(consumer_5, &retval);
    pthread_join(producer_6, &retval);
    pthread_join(consumer_6, &retval);
    pthread_join(producer_7, &retval);
    pthread_join(consumer_7, &retval);
    pthread_join(producer_8, &retval);
    pthread_join(consumer_8, &retval);
    pthread_join(producer_9, &retval);
    pthread_join(consumer_9, &retval);
    pthread_join(producer_10, &retval);
    pthread_join(consumer_10, &retval);
    pthread_join(producer_11, &retval);
    pthread_join(consumer_11, &retval);
    pthread_join(producer_12, &retval);
    pthread_join(consumer_12, &retval);
    pthread_join(producer_13, &retval);
    pthread_join(consumer_13, &retval);
    pthread_join(producer_14, &retval);
    pthread_join(consumer_14, &retval);
    pthread_join(producer_15, &retval);
    pthread_join(consumer_15, &retval);
    pthread_join(producer_16, &retval);
    pthread_join(consumer_16, &retval);
    pthread_join(producer_17, &retval);
    pthread_join(consumer_17, &retval);
    pthread_join(producer_18, &retval);
    pthread_join(consumer_18, &retval);
    pthread_join(producer_19, &retval);
    pthread_join(consumer_19, &retval);
    pthread_join(producer_20, &retval);
    pthread_join(consumer_20, &retval);
    pthread_join(producer_21, &retval);
    pthread_join(consumer_21, &retval);
    pthread_join(producer_22, &retval);
    pthread_join(consumer_22, &retval);
    pthread_join(producer_23, &retval);
    pthread_join(consumer_23, &retval);
    pthread_join(producer_24, &retval);
    pthread_join(consumer_24, &retval);
    pthread_join(producer_25, &retval);
    pthread_join(consumer_25, &retval);
    pthread_join(producer_26, &retval);
    pthread_join(consumer_26, &retval);
    pthread_join(producer_27, &retval);
    pthread_join(consumer_27, &retval);
    pthread_join(producer_28, &retval);
    pthread_join(consumer_28, &retval);
    pthread_join(producer_29, &retval);
    pthread_join(consumer_29, &retval);
    pthread_join(producer_30, &retval);
    pthread_join(consumer_30, &retval);
    return 0;
}

 

 总结: 

         通过生产者消费者线程的练习,使我了解了线程同步互斥之间的区别,并且对信号量的运用更加纯熟。本程序用linux的gcc编译器运行的,使我对linux操作系统的C语言编程更加了解,由于第一次使用linux的POSIX库,因此运用起来不是那么纯熟,例如创建生产者和消费者线程的创建没有用到合适的线程数组,希望能在以后的学习中不断地完善,不要做代码的机器,不要冗余的代码,要言简意赅!!!!!

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值