用多线程实现“生产者-消费者问题”(代码+实验报告)

本文介绍了一个基于Windows多线程API实现的生产者-消费者问题解决方案。通过设置信号量和互斥量来确保多线程环境下的数据一致性,并详细展示了具体的代码实现。

用多线程实现“生产者-消费者问题”(代码+实验报告)

  1. #include<iostream>
  2. #include<stdlib.h>
  3. #include<STDIO.H>
  4. #include<windows.h>
  5. usingnamespacestd;
  6. typedefintsemaphore;/*信号量是一种特殊的整型变量*/
  7. constintSIZE_OF_BUFFER=5;//缓冲区长度
  8. constunsignedshortPRODUCERS_COUNT=2;//生产者的个数
  9. constunsignedshortCONSUMERS_COUNT=3;//消费者的个数
  10. DWORDproducers[PRODUCERS_COUNT];//生产者线程的标识符
  11. DWORDconsumers[CONSUMERS_COUNT];//消费者线程的标识符
  12. constunsignedshortTHREADS_COUNT=PRODUCERS_COUNT+CONSUMERS_COUNT;//总的线程数
  13. /**
  14. *定义信号量
  15. */
  16. HANDLEmutex;//互斥信号量
  17. HANDLEfull;//表示放有产品的缓冲区数,其初值为0
  18. HANDLEempty;//表示可供使用的缓冲区数,其初值为N
  19. /**
  20. *定义共享缓冲区
  21. */
  22. semaphorebuffer[SIZE_OF_BUFFER];
  23. /**
  24. *定义生产者和消费者使用的指针
  25. */
  26. intin=0;
  27. intout=0;
  28. intproductNum=0;
  29. DWORDWINAPIProducer(LPVOID);
  30. DWORDWINAPIConsumer(LPVOID);
  31. intmain(intargc,char*argv[])
  32. {
  33. //创建Mutex和Semaphore
  34. mutex=CreateMutex(NULL,FALSE,NULL);
  35. full=CreateSemaphore(NULL,0,SIZE_OF_BUFFER,NULL);
  36. empty=CreateSemaphore(NULL,SIZE_OF_BUFFER,SIZE_OF_BUFFER,NULL);
  37. HANDLEPVThreads[THREADS_COUNT];//各线程的handle
  38. //创建生产者线程
  39. for(inti=0;i<PRODUCERS_COUNT;i++){
  40. PVThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producers[i]);
  41. if(PVThreads[i]==NULL)break;
  42. }
  43. //创建消费者线程
  44. for(inti=0;i<CONSUMERS_COUNT;i++){
  45. PVThreads[PRODUCERS_COUNT+i]
  46. =CreateThread(NULL,0,Consumer,NULL,0,&consumers[i]);
  47. if(PVThreads[i]==NULL)break;
  48. }
  49. boolisContinue=true;
  50. while(isContinue)
  51. {
  52. if(getchar()){//按回车后终止程序运行
  53. isContinue=false;
  54. }
  55. }
  56. system("PAUSE");
  57. return0;
  58. }
  59. voidenBuffer(intpos)
  60. {
  61. cout<<"正在生产产品..."<<endl;
  62. Sleep(2000);
  63. buffer[pos]=-1;
  64. productNum++;
  65. cout<<"生产完成!已生产"<<productNum<<"个产品,并将新产品放在了缓冲区位置:"<<pos<<endl;
  66. }
  67. voiddeBuffer(intpos)
  68. {
  69. cout<<"正在消费产品..."<<endl;
  70. Sleep(1000);
  71. buffer[pos]=-2;
  72. productNum--;
  73. cout<<"已消费在缓冲区位置:"<<pos<<"的产品,缓冲区剩余空间:"<<SIZE_OF_BUFFER-productNum<<endl;
  74. cout<<endl;
  75. }
  76. /**
  77. *生产者
  78. */
  79. DWORDWINAPIProducer(LPVOIDlpParam)
  80. {
  81. while(1)
  82. {
  83. WaitForSingleObject(empty,INFINITE);//P(empty)生产者信号量-1
  84. WaitForSingleObject(mutex,INFINITE);//P(mutex)获取线程间互斥信号
  85. enBuffer(in);
  86. Sleep(1000);
  87. in=(in+1)%SIZE_OF_BUFFER;
  88. ReleaseMutex(mutex);//V(mutex)释放线程间互斥信号
  89. ReleaseSemaphore(full,1,NULL);//V(full)消费者信号量+1
  90. }
  91. return0;
  92. }
  93. /**
  94. *消费者
  95. */
  96. DWORDWINAPIConsumer(LPVOIDlpPara)
  97. {
  98. while(1)
  99. {
  100. WaitForSingleObject(full,INFINITE)==WAIT_ABANDONED;//P(full)消费者信号量-1
  101. WaitForSingleObject(mutex,INFINITE);//P(mutex)获得线程间互斥信号
  102. deBuffer(out);
  103. Sleep(1000);
  104. out=(out+1)%SIZE_OF_BUFFER;
  105. ReleaseMutex(mutex);//V(mutex)释放线程间互斥信号
  106. ReleaseSemaphore(empty,1,NULL);//V(empty)生产者信号量+1
  107. }
  108. return0;
  109. }

北航软件学院《一级实践》实验报告<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

学号:GS0821594  姓名:叶现                  第 11 周

内容

训练

用多线程实现“生产者-消费者问题”

解决该问题的思路

假设有一组(多个)生产者和一组(多个)消费者,生产者负责生产物品,然后将物品放置在一个缓冲区中供消费者消费。消费者从缓冲区取走物品。假定缓冲区共有N,不妨把它们设想成一个环形缓冲池。如下图所示:

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><shapetype id="_x0000_t75" coordsize="21600,21600" o:preferrelative="t" o:spt="75" filled="f" stroked="f" path=" m@4@5 l@4@11@9@11@9@5 xe"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0 "></f><f eqn="sum @0 1 0 "></f><f eqn="sum 0 0 @1 "></f><f eqn="prod @2 1 2 "></f><f eqn="prod @3 21600 pixelWidth "></f><f eqn="prod @3 21600 pixelHeight "></f><f eqn="sum @0 0 1 "></f><f eqn="prod @6 1 2 "></f><f eqn="prod @7 21600 pixelWidth "></f><f eqn="sum @8 21600 0 "></f><f eqn="prod @7 21600 pixelHeight "></f><f eqn="sum @10 21600 0 "></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 360.75pt; HEIGHT: 102pt" coordsize="21600,21600" type="#_x0000_t75"><imagedata o:title="" src="file0950.files/image001.png"></imagedata></shape>

中,阴影部分表示该缓冲区中放有的产品,否则为空。In表示生产者下次存入产品的单元;out表示消费者下次取出产品的单元。

1) 为使这两类进程协调工作,防止盲目的生产和消费,它们应满足如下同步条件:时刻所有生产者存放产品的单元数不能超过缓冲区的总容量(N)。

2) 所有消费者取出产品的总量不能超过所有生产者当前生产产品的总量。

设缓冲区的编号为0~N-1,inout分别是生产者进程和消费者进程使用的指针,指向下面可用的缓冲区,初值都是0

为使两类进程实行同步操作,应设置三个信号量:两个计数信号量fullempty,一个互斥信号量mutex

full:表示放有产品的缓冲区数,其初值为0

empty:表示可供使用的缓冲区数,其初值为N

mutex:互斥信号量,初值为1表示各进程互斥进入临界区,保证任何时候只有一个进程使用缓冲区。

下面是解决这个问题的算法描述。

生产者进程Producer

消费者进程Consumer

while(TRUE)

{

P(empty);

P(mutex)

产品送往bufferin);

in=(in+1)mod n

V(mutex);

V(full);

}

while(TRUE)

{

P(full);

P(mutex)

bufferout)中取出产品;

in=(in+1)mod n

V(mutex);

V(empty);

}

在生产者消费者问题中需满足下面三点:

1) 在每个程序中坐须先做P(mutex),后做V(mutex),二者要成对出现。夹在二者中间的代码段就是该进程的监界区。

2) 对同步信号量fullemptyPV操作同样必须成对出现,但它们分别位于不同的程序中。

3) 无论在生产者进程中还是在消费者进程中,两个P操作的次序不能颠倒:应先执行同 步信号量的P操作,然后执行互斥信号量的P操作。否则可能造成进程死锁。

本周开发源代码

代码的功能简述

用多线程实现“生产者-消费者问题”

开发的收获

关于Windows多线程API的使用;

深入了解了进程互斥问题

开发中碰到的主要困难

1) 关于Windows多线程API的使用:

2) “生产者-消费者问题”问题的实现机制

开发中未能解决的问题

针对本周训练内容自己设计的案例

案例的主要功能

多线程实现“生产者-消费者问题”

用到的基本知识

进程同步与互斥原理;临界资源和临界区的相关定义;几种互斥的实现方式;关于信号量的使用及其实现方式

程序注意了哪些规范

代码格式、常量的定义、函数的声明

你进行了哪些测试

程序进行了哪些有效性检查

你是如何保证程序的高效率的

注意:实验报告和案例源代码须在本次小组讨论会前提交

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值