论文格式
电气工程 会计论文 金融论文 国际贸易 财务管理 人力资源 轻化工程 德语论文 工程管理 文化产业管理 信息计算科学 电气自动化 历史论文
机械设计 电子通信 英语论文 物流论文 电子商务 法律论文 工商管理 旅游管理 市场营销 电视制片管理 材料科学工程 汉语言文学 免费获取
制药工程 生物工程 包装工程 模具设计 测控专业 工业工程 教育管理 行政管理 应用物理 电子信息工程 服装设计工程 教育技术学 论文降重
通信工程 电子机电 印刷工程 土木工程 交通工程 食品科学 艺术设计 新闻专业 信息管理 给水排水工程 化学工程工艺 推广赚积分 付款方式
  • 首页 |
  • 毕业论文 |
  • 论文格式 |
  • 个人简历 |
  • 工作总结 |
  • 入党申请书 |
  • 求职信 |
  • 入团申请书 |
  • 工作计划 |
  • 免费论文 |
  • 现成论文 |
  • 论文同学网 |
搜索 高级搜索

当前位置:论文格式网 -> 免费论文 -> 其他论文

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

本论文在其他论文栏目,由论文格式网整理,转载请注明来源www.lwgsw.com,更多论文,请点论文格式范文查看

1 设计题目与要求
 1.1题目:
用多线程同步方法解决生产者-消费者问题(Bounded - Buffer Problem)
 1.2目的:
通过研究Linux的线程机制和信号量实现生产者消费者问题的并发控制。
 1.3说明:
有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数。
 1.4要求:
 1.4.1 每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前指针位置和生产者/消费者线程的标识符。
 1.4.2 生产者和消费者各有两个以上。
 1.4.3 多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。
2 总的设计思想
 2.1问题描述
 生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
 2.2 设计思想
 Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。clone()是Linux所特有的系统调用,它的使用方式类似fork。
 信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。当公共资源增加时,调用函数sem_post()增加信号量。只有当信号量值大于0时,才能使用公共资源,使用后,函数sem_wait()减少信号量。函数sem_trywait()和函数pthread_ mutex_trylock()起同样的作用,它是函数sem_wait()的非阻塞版本。下面我们逐个介绍和信号量有关的一些函数,它们都在头文件/usr/include/semaphore.h中定义。
  pthread提供的程序并发控制有:
pthread_create()    /*创建新的进程*/
pthread_join()     /*等待的进程的结束*/
sem_init()          /*信号量初始化*/
sem_wait();        /*信号量wait操作*/
sem_post();       /*信号量signal操作*/
phtread_mutex_init()  /*互斥量初始化*/
phtread_mutex_lock()    /*互斥量P操作*/
pthread_mutex_unck()    /*互斥量V操作*/
3 系统平台、语言、工具等
系统平台:linux操作系统
 语言:    linux下的C语言编程
 工具:    Linux主机 以及终端
 3.1硬件及软件支持环境
 硬件要求不高,普通PC机即可。本程序的开发利用需要PC 装有linux系统,或者linux终端,他是开发核运行程序的环境。Linux 并发程序支持库pthread , pthread 是符合POSIX标准的多线程库。
 3.2开发环境
   vi       文本编辑
   gcc    c语言编译程序
4 数据结构与模块说明
 4.1 数据结构及功能
 本程序中的数据结构比较简单,采用长度为20的数组来存放生产者生产的物品。用数组的下标来表示当前指针的位置。
主程序:
int main()
{
  pthread_t  p1,p2,p3…..pn,c1,c2,c3……cn;
  int ret,i;
  sem_init(&empty,0,MAX);  //初始化信号量
  sem_init(&full,0,0);
  sem_init(&mutex,0,1);
  srand(time(0));
  for(i=0;i<MAX;i++)
     buffer[i]=0;
创建线程:
ret = pthread_create(&pn,NULL,producer,(void*)n);  //创建生产者线程
 if(ret)
     {
        printf("create producern error!");
        abort();
     }
ret =pthread_create(&cn,NULL,consumer,(void*)n);  //创建消费者线程
 if(ret)
      {
         printf("create consumern error !");
         abort();
      }
生产者线程:
void *producer(void *threadid)
{
int i=0;
while(1)
 {
   sem_wait(&empty);
   sem_wait(&mutex);
       …………
   sem_post(&mutex);
   sem_post(&full);
 }
}
消费者线程:
void *consumer(void *threadid)
{
 int i=0;
 while(1)
 {
  sem_wait(&full);
  sem_wait(&mutex);
   …………
  sem_post(&mutex);
  sem_post(&empty);
  }
}
 4.2 流程图


5 用户名、源程序名、目标程序名及源程序
主机IP:192.168.1.200
目录:.../home/j030126/
用户名:j030126
源程序名:pro_cus.c
目标程序名:pro_cus
源程序
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MAX 20
int buffer[MAX];
int size=0;
sem_t empty, full, mutex;
void *producer(void* threadid);
void *consumer(void* threadid);

int main()
{
  pthread_t p1,p2,p3,c1,c2,c3;
  int ret,i;
  sem_init(&empty,0,MAX);
  sem_init(&full,0,0);
  sem_init(&mutex,0,1);
  srand(time(0));
  for(i=0;i<MAX;i++)
     buffer[i]=0;

  ret =pthread_create(&p1,NULL,consumer,(void*)1);
  if(ret)
      {
         printf("create consumer1 error !");
         abort();
      }
   ret = pthread_create(&c1,NULL,producer,(void*)1);
  if(ret)
     {
        printf("create producer1 error!");
        abort();
     }
  ret =pthread_create(&p2,NULL,consumer,(void*)2);
  if(ret)
      {
         printf("create consumer2 error !");
         abort();
      }
  ret = pthread_create(&c2,NULL,producer,(void*)2);
  if(ret)
     {
        printf("create producer2 error!");
        abort();
     }
  ret =pthread_create(&p3,NULL,consumer,(void*)3);
  if(ret)
      {
         printf("create consumer3 error !");
         abort();
      }
  ret = pthread_create(&c3,NULL,producer,(void*)3);
  if(ret)
     {
        printf("create producer3 error!");
        abort();
     }
 pthread_join(p1,NULL);
 pthread_join(c1,NULL);
 pthread_join(p2,NULL);
 pthread_join(c2,NULL);
 pthread_join(p3,NULL);
 pthread_join(c3,NULL);
}

void *producer(void *threadid)
{
int i=0;
while(1)
{
   sleep(1);
   sem_wait(&empty);
   sem_wait(&mutex);
       buffer[(size++)%MAX]=1;
       for(i=0;i<MAX;i++)
          printf("%d",buffer[i]);
       printf("\nThis is Product %d thread.\n",(int)threadid);
   sem_post(&mutex);
   sem_post(&full);
   sleep(1);
 }
}

void *consumer(void *threadid)
{
int i=0;
while(1)
{
  sleep(rand()%2+1);
  sem_wait(&full);
  sem_wait(&mutex);
    /*buffer[(--size+MAX)%MAX]=0;*/
    for(i=0;i<MAX;i++)
       {
        if(buffer[i]==1) {buffer[i]=0;break;} 
          printf("%d",buffer[i]);
        }
    for(;i<MAX;i++)
        printf("%d",buffer[i]);
    printf("\nThis is Customer %d thread.\n",(int)threadid);
  sem_post(&mutex);
  sem_post(&empty);
  sleep(rand()%2+1);
  }
}

6 运行结果与运行情况
 本程序运行是随机的,每次运行的结果是不一样的,生产者线程和消费者线程是抢占式的运行,生产者线程和消费者线程数分别为3,生产的产品按顺序存放在存储单元,如果存储单元有产品(显示为1,无产品则为0),那么消费者按顺序消费最先生产出来的产品。这里存在潜在的竞争条件,所谓竞争条件就是这样一种情况:多个线程对数据产生的作用要依赖于线程的调度顺序的。当两个线程竞相访问同一数据时,就会发生竞争条件。


7 调试报告
 7.1调试记录
 本问题主要是实现进程同步和竞争的问题。因此程序最主要的是解决进程间的同步问题。为了清晰地表示出他们的调度过程,需要在调度的同时显示他们的标识符。缓冲区内容和当前指针位置也要显示以帮助理解,还可以当程序出错时帮助分析错误原因。另外题目还要求至少要有两个生产者、两个消费者。
 在这个实例中,首先定义了一个大小为20的公共缓冲区,也就是临界资源,然后的buffer[MAX]便是缓冲区中产品的数目,初始化为0。producer函数是生产者函数,produce_item(&item);是指生产者生产出来一个产品,但是这时候并没有对缓冲区进行操作。在这里一开始出现了些小问题,就是在定义变量的时候忘记了格式,所以开始调试程序的时候出现很多提示错误,后来再仔细的查看了资料后,才纠正了错误的定义方式。if (count==N) sleep();是测试语句,如果生产出来的产品数和缓冲区大小相等时,生产者就进入睡眠状态。如果不等,产品就放入缓冲区内,并且产品数增加1。if (count==1) wakeup(consumer);这条语句的意思是,如果上一次操作时产品的数目为0,消费者已经进入了睡眠状态,而现在生产者又生产出来一个产品,缓冲区内不为空,这时把消费者唤醒。消费者函数也是同样的道理,只不过一个是取,另一个是放。我们可以看到,这里存在潜在的竞争条件,所谓竞争条件就是这样一种情况:多个线程对数据产生的作用要依赖于线程的调度顺序的。当两个线程竞相访问同一数据时,就会发生竞争条件。由于时间片的原因,一个线程可以在任意一个时刻打断其他线程,因此数据可能会被破坏或者被错误地解释。还有在编写代码时出现了许多常规错误如函数名输入错误、变量没有提前声明就使用、缺少头文件等。在整个程序的调试过程中最让我头疼的一个问题就是创建线程时数组的指针出了错,运行时提示有段错误,这让我一开始根本不知道是怎么回事,在求助了同学的基础上,我查阅了下资料,发现很可能是在指针上出现了问题,仔细研究了程序后,觉得可能是指针在指向地址时由于指向冲突而引起的,所以我把原来的生产者、消费者线程标识符pro、con分别改为proid、conid,以跟生产者和消费者线程子函数名 pro、con 区别开来,避免指针地址同名。然后再次运行程序,终于可以顺利执行。
 7.2自我评析和总结
 在动手实现该程序的过程中,加深了对信号量、线程、等待与同步等重要概念的理解,也提高了自己使用linux编写C程序的能力。同时,也锻炼了自己动手解决问题,查阅相关资料的能力.在具体编写代码时,通过实践也认识到养成良好的编码习惯的重要性.正确的代码书写习惯和格式,可以提高程序的可读性、可调试性。
 
8 参考文献
 《操作系统概念》   Abraham silberschatz
        Peter Baer Galvin
        Greg Gagne   编          高等教育出版社
 《操作系统基础》        屠立德    等编        清华大学出版社


相关论文
上一篇:中国武术进入北京奥运会比赛项目.. 下一篇:浅谈电子商务的信息安全问题
Tags:线程 同步 方法 解决 生产者 消费者 问题 【收藏】 【返回顶部】
人力资源论文
金融论文
会计论文
财务论文
法律论文
物流论文
工商管理论文
其他论文
保险学免费论文
财政学免费论文
工程管理免费论文
经济学免费论文
市场营销免费论文
投资学免费论文
信息管理免费论文
行政管理免费论文
财务会计论文格式
数学教育论文格式
数学与应用数学论文
物流论文格式范文
财务管理论文格式
营销论文格式范文
人力资源论文格式
电子商务毕业论文
法律专业毕业论文
工商管理毕业论文
汉语言文学论文
计算机毕业论文
教育管理毕业论文
现代教育技术论文
小学教育毕业论文
心理学毕业论文
学前教育毕业论文
中文系文学论文
最新文章
热门文章
计算机论文
推荐文章

本站部分文章来自网络,如发现侵犯了您的权益,请联系指出,本站及时确认删除 E-mail:349991040@qq.com

论文格式网(www.lwgsw.com--论文格式网拼音首字母组合)提供其他论文毕业论文格式,论文格式范文,毕业论文范文

Copyright@ 2010-2018 LWGSW.com 论文格式网 版权所有