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

题目要求:

有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-2020个整型数。

设计要求:(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者线程的标识符.(2)生产者和消费者各有两个以上.(3)多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码。

 

 

源程序:

 

 

#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <time.h>
#include <stdlib.h>
#define NUM 20                                                       //缓冲区大小
int queue[NUM];                                                       //定义缓冲区
static int p = 0,c=0,p1=0;                                          //p为生产者放入数据时的数组下标,c为消费者取出数据时的数组下标,p1为缓冲区内容中第一个数据在数组中的下标
pthread_t p1id,c1id,p2id,c2id,p3id,c3id;              //定义变量,存储线程的标识符
sem_t blank_number, product_number;                       //blank_number存储空存储单元的个数,product_number存储放入数据的个数
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;//实现对queue[NUM]的互斥访问
void *producer1(void *arg)                                        //随机生成1-20这20个整型数
{
while(1)
{                                               
sem_wait(&blank_number);                                     //检查是否有空的存储单元
pthread_mutex_lock(&lock);                                   //检查缓冲区是否可用
queue[p] = rand()%20+1;                                      //随机生成1-20这20个整型数,并放入缓冲区
printf("Produce1 生成了随机数 %d/n", queue[p]);       //输出
printf("随机生成1-20这20个整型数,并放入缓冲区/n");
printf("当前指针位置: %d /n",p);                              //放入数据后,下一个将要存放数据的数组下标
p = (p+1)%NUM;                                                //防止数组下标越界
printf("缓冲区内容为:");
if (p1<p)                                                          //当缓冲区内容的第一个数据的数组下标小于最后一个数据的数组下标时,实现输出
{
int j=p1;
while(j<p)                                                        //循环输出
{
printf("%d  ",queue[j]);
j++;
}
}
else                                                                 //当缓冲区内容的第一个数据的数组下标大于最后一个数据的数组下标时,通过选择结构,分成两部分实现输出
{
int j=p1;
while(j<=19)                                                   //循环输出
{
printf("%d  ",queue[j]);
j++;
}
int k=0;
while(k<p)                                                      //循环输出

printf("%d  ",queue[k]);
k++;
}
}
printf("/n");
p1id=pthread_self();                                        //获取线程的标识符,然后赋给变量
printf("线程producer1的标识符: %u/n",p1id);       //输出
printf("/n/n/n");
pthread_mutex_unlock(&lock);                          //解锁,换位置后可能产生死锁
sleep(rand()%5);                                           //随机等待5秒之内的时间
sem_post(&product_number);                            //product_number加1
}
}
void *producer2(void *arg)                             //随机生成1-20这20个整型数
{
while(1)
{
sem_wait(&blank_number);                           //检查是否有空的存储单元
pthread_mutex_lock(&lock);                       //检查缓冲区是否可用
queue[p] = rand()%20+1;                         //随机生成1-20这20个整型数,并放入缓冲区
printf("Produce2 生成了随机数 %d/n", queue[p]);
printf("随机生成1-20这20个整型数,并放入缓冲区/n");
printf("当前指针位置: %d /n",p);               //放入数据后,下一个将要存放数据的数组下标
p = (p+1)%NUM;                                     //防止数组下标越界
printf("缓冲区内容为:");
if (p1<p)                                                 //当缓冲区内容的第一个数据的数组下标小于最后一个数据的数组下标时,实现输出
{
int j=p1;
while(j<p)
{
printf("%d  ",queue[j]);
j++;
}
}
else                                                          //当缓冲区内容的第一个数据的数组下标大于最后一个数据的数组下标时,通过选择结构,分成两部分实现输出
{
int j=p1;
while(j<=19)
{
printf("%d  ",queue[j]);
j++;
}
int k=0;
while(k<p)
{
printf("%d  ",queue[k]);
k++;
}
}
printf("/n");
p2id=pthread_self();                                       //获取线程的标识符,然后赋给变量
printf("线程producer2的标识符: %u/n",p2id);
printf("/n/n/n");
pthread_mutex_unlock(&lock);                            //解锁,换位置后可能产生死锁
sleep(rand()%5);                                               //随机等待5秒之内的时间
sem_post(&product_number);                              //product_number加1
}
}
void *producer3(void *arg)                               //随机生成1-20这20个整型数
{
while(1)
{
sem_wait(&blank_number);                               //检查是否有空的存储单元
pthread_mutex_lock(&lock);                               //检查缓冲区是否可用
queue[p] = rand()%20+1;                               //随机生成1-20这20个整型数,并放入缓冲区
printf("Produce3 生成了随机数 %d/n", queue[p]);
printf("随机生成1-20这20个整型数,并放入缓冲区/n");
printf("当前指针位置: %d /n",p);                   //放入数据后,下一个将要存放数据的数组下标
p = (p+1)%NUM;                                       //防止数组下标越界
printf("缓冲区内容为:");
if (p1<p)                                                     //当缓冲区内容的第一个数据的数组下标小于最后一个数据的数组下标时,实现输出
{
int j=p1;
while(j<p)
{
printf("%d  ",queue[j]);
j++;
}
}
else                                                         //当缓冲区内容的第一个数据的数组下标大于最后一个数据的数组下标时,通过选择结构,分成两部分实现输出
{
int j=p1;
while(j<=19)
{
printf("%d  ",queue[j]);
j++;
}
int k=0;
while(k<p)
{
printf("%d  ",queue[k]);
k++;
}
}
printf("/n");
p3id=pthread_self();                                        //获取线程的标识符,然后赋给变量
printf("线程producer3的标识符: %u/n",p3id);
printf("/n/n/n");
pthread_mutex_unlock(&lock);                           //解锁,换位置后可能产生死锁
sleep(rand()%5);                                              //随机等待5秒之内的时间
sem_post(&product_number);                              //product_number加1
}
}
void *consumer1(void *arg)                                //显示取出的内容
{
while(1)
{
sem_wait(&product_number);                             //检查缓冲区中是否有可以取出的数据
pthread_mutex_lock(&lock);                                  //检查缓冲区是否可用
printf("Consume1 取出随机数 %d/n", queue[c]);
printf("当前指针位置: %d /n",c);                     //取出数据后,下一个将要被取数据的数组下标
c = (c+1)%NUM;                                             //防止数组下标越界
p1= (p1+1)%NUM;                                          //防止数组下标越界
printf("缓冲区内容为:");
if (p1<p)                                                          //当缓冲区内容的第一个数据的数组下标小于最后一个数据的数组下标时,实现输出
{
int j=p1;
while(j<p)
{
printf("%d  ",queue[j]);
j++;
}
}
else                                                                //当缓冲区内容的第一个数据的数组下标大于最后一个数据的数组下标时,通过选择结构,分成两部分实现输出
{
int j=p1;
while(j<=19)
{
printf("%d  ",queue[j]);
j++;
}
int k=0;
while(k<p)
{
printf("%d  ",queue[k]);
k++;
}
}
printf("/n");
c1id=pthread_self();                                        //获取线程的标识符,然后赋给变量
printf("线程Consume1的标识符: %u/n",c1id);
printf("/n/n/n");
pthread_mutex_unlock(&lock);                            //解锁,换位置后可能产生死锁
sleep(rand()%5);                                                  //随机等待5秒之内的时间
sem_post(&blank_number);                                    //blank_number加1
}
}
void *consumer2(void *arg)                                 //显示取出的内容
{
while(1)
{
sem_wait(&product_number);                               //检查缓冲区中是否有可以取出的数据
pthread_mutex_lock(&lock);                                    //检查缓冲区是否可用
printf("Consume2 取出随机数 %d/n", queue[c]);
printf("当前指针位置: %d /n",c);                            //取出数据后,下一个将要被取数据的数组下标
c = (c+1)%NUM;                                                    //防止数组下标越界
p1= (p1+1)%NUM;                                                 //防止数组下标越界
printf("缓冲区内容为:");
if (p1<p)                                                               //当缓冲区内容的第一个数据的数组下标小于最后一个数据的数组下标时,实现输出
{
int j=p1;
while(j<p)
{
printf("%d  ",queue[j]);
j++;
}
}
else                                                                     //当缓冲区内容的第一个数据的数组下标大于最后一个数据的数组下标时,通过选择结构,分成两部分实现输出
{
int j=p1;
while(j<=19)
{
printf("%d  ",queue[j]);
j++;
}
int k=0;
while(k<p)
{
printf("%d  ",queue[k]);
k++;
}
}
printf("/n");
c2id=pthread_self();                                             //获取线程的标识符,然后赋给变量
printf("线程Consume2的标识符: %u/n",c2id);
printf("/n/n/n");
pthread_mutex_unlock(&lock);                                //解锁,换位置后可能产生死锁
sleep(rand()%5);                                                        //随机等待5秒之内的时间
sem_post(&blank_number);                                    //blank_number加1
}
}
void *consumer3(void *arg)                                   //显示取出的内容
{
while(1)
{
sem_wait(&product_number);                              //检查缓冲区中是否有可以取出的数据
pthread_mutex_lock(&lock);                                    //检查缓冲区是否可用 
printf("Consume3 取出随机数 %d/n", queue[c]);
printf("当前指针位置: %d /n",c);                            //取出数据后,下一个将要被取数据的数组下标
c = (c+1)%NUM;                                                   //防止数组下标越界
p1= (p1+1)%NUM;                                                   //防止数组下标越界
printf("缓冲区内容为:");
if (p1<p)                                                             //当缓冲区内容的第一个数据的数组下标小于最后一个数据的数组下标时,实现输出
{
int j=p1;
while(j<p)
{
printf("%d  ",queue[j]);
j++;
}
}
else                                                                  //当缓冲区内容的第一个数据的数组下标大于最后一个数据的数组下标时,通过选择结构,分成两部分实现输出
{
int j=p1;
while(j<=19)
{
printf("%d  ",queue[j]);
j++;
}
int k=0;
while(k<p)
{
printf("%d  ",queue[k]);
k++;
}
}
printf("/n");
c3id=pthread_self();                                                 //获取线程的标识符,然后赋给变量
printf("线程Consume3的标识符:%u/n",c3id);
printf("/n/n/n");
pthread_mutex_unlock(&lock);                                       //解锁,换位置后可能产生死锁
sleep(rand()%5);                                                            //随机等待5秒之内的时间
sem_post(&blank_number);                                                //blank_number加1
}
}
int main(int argc, char *argv[])
{
time_t t;
srand((unsigned) time(&t));               //是每次使随机数不同。也等同于种一个随机的种子。(从网上搜的)
sem_init(&blank_number, 0, NUM);                                   //初始化一个blank_number变量,0表示信号量用于同一进程的线程间同步,NUM表示可用资源的数量
sem_init(&product_number, 0, 0);
pthread_create(&p1id, NULL, producer1, NULL);                 //创建线程
pthread_create(&c1id, NULL, consumer1, NULL);
pthread_create(&p2id, NULL, producer2, NULL);
pthread_create(&c2id, NULL, consumer2, NULL);
pthread_create(&p3id, NULL, producer3, NULL);
pthread_create(&c3id, NULL, consumer3, NULL);
pthread_join(p1id, NULL);                                                   //主线程将挂起等待,直到producer1终止
pthread_join(c1id, NULL);
pthread_join(p2id, NULL);
pthread_join(c2id, NULL);
pthread_join(p3id, NULL);
pthread_join(c3id, NULL);
sem_destroy(&blank_number);                                           // 释放与semaphore相关的资源
sem_destroy(&product_number);
return 0;
}

程序运行结果:

 

 

 

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值