生产者与消费者算法13540.docx
#inccludde<wwinddowss.h>>#inccludde<ffstrreamm.h>>#inccludde<sstdiio.hh>#inccludde<sstriing>>#inccludde<cconiio.hh>/定义义一些常常量;/本程程序允许许的最大大临界区区数;#deffinee MAAX_BBUFFFER_NUMM 100/秒到到微秒的的乘法因因子;#deffinee INNTE_PERR_SEEC 110000/本程程序允许许的生产产和消费费线程的的总数;#deffinee MAAX_TTHREEAD_NUMM 644/定义义一个结结构,记记录在测测试文件件中指定定的每一一个线程程的参数数struuct ThrreaddInffo intt seeriaal; /线程序序列号 chaar eentiity; /是PP还是CC douublee deelayy; /线程程延迟 intt thhreaad_rrequuesttMAAX_TTHREEAD_NUMM; /线程请请求队列列 intt n_reqquesst; /请请求个数数;/全局局变量的的定义/临界界区对象象的声明明,用于于管理缓缓冲区的的互斥访访问;CRITTICAAL_SSECTTIONN PCC_CrritiicallMAAX_BBUFFFER_NUMM; int BBufffer_CriiticcalMAXX_BUUFFEER_NNUM; /缓冲冲区声明明,用于于存放产产品;HANDDLE h_TThreeadMAXX_THHREAAD_NNUM; /用用于存储储每个线线程句柄柄的数组组;ThreeadIInfoo Thhreaad_IInfooMAAX_TTHREEAD_NUMM; /线程信信息数组组;HANDDLE emppty_semmaphhoree; /一个信信号量;HANDDLE h_mmuteex; /一个互互斥量;DWORRD n_TThreead = 00; /实际际的线程程的数目目;DWORRD n_BBufffer_or_Criiticcal; /实际际的缓冲冲区或者者临界区区的数目目;HANDDLE h_SSemaaphooreMAXX_THHREAAD_NNUM; /生产产者允许许消费者者开始消消费的信信号量;/生产产消费及及辅助函函数的声声明voidd PProdducee(vooid *p);voidd CConssumee(vooid *p); booll IIfInnOthherRRequuestt(innt);int FFinddProoduccePoositton();int FFinddBuffferrPossitiion(intt);int maiin(vvoidd) /声声明所需需变量; DWOORD waait_forr_alll; ifsstreeam inFFilee; /初初始化缓缓冲区; forr(innt ii=0;i< MAXX_BUUFFEER_NNUM;i+) Buuffeer_CCritticaalii = -11; /初初始化每每个线程程的请求求队列; forr(innt jj=0;j<MMAX_THRREADD_NUUM;jj+) foor(iint k=00;k<<MAXX_THHREAAD_NNUM;k+) TThreead_Inffojj.tthreead_reqquesstkk = -11; Thhreaad_IInfooj.n_reqquesst = 0; /初初始化临临界区; forr(i =0;i< MAXX_BUUFFEER_NNUM;i+) InnitiialiizeCCritticaalSeectiion(&PCC_Crritiicalli); /打打开输入入文件,按按照规定定的格式式提取线线程等信信息; inFFilee.oppen("teest.txtt"); /从从文件中中获得实实际的缓缓冲区的的数目; inFFilee >>> n_Buffferr_orr_Crritiicall; inFFilee.geet(); priintff("输输入文件件是:n"); /回回显获得得的缓冲冲区的数数目信息息; priintff("%d n",(innt) n_BBufffer_or_Criiticcal); /提提取每个个线程的的信息到到相应数数据结构构中; whiile(inFFilee) innFille >>> TThreead_Inffonn_Thhreaad.serriall; innFille >>> TThreead_Inffonn_Thhreaad.enttityy; innFille >>> TThreead_Inffonn_Thhreaad.dellay; chhar c; inFFilee.geet(cc); whhilee(c!='n'&&& !inFFilee.eoof() iinFiile>>> TThreead_Inffonn_Thhreaad.thrreadd_reequeestThrreadd_Innfon_TThreead.n_reqquesst+; iinFiile.gett(c); n_Thrreadd+; /回回显获得得的线程程信息,便便于确认认正确性性; forr(j=0;jj<(iint) n_Thrreadd;j+) innt TTempp_seeriaal = TThreead_Inffojj.sseriial; chhar TTempp_enntitty = TThreead_Inffojj.eentiity; dooublle TTempp_deelayy = TThreead_Inffojj.ddelaay; prrinttf("" nn thhreaad%22d %c %f ",Temmp_sseriial,Temmp_eentiity,Temmp_ddelaay); innt TTempp_reequeest = TThreead_Inffojj.nn_reequeest; foor(iint k=00;k<<Temmp_rrequuestt;k+) pprinntf(" %d "", TThreead_Inffojj.tthreead_reqquesstkk); coout<<<enndl; priintff("nnn");/创建建在模拟拟过程中中几个必必要的信信号量 emppty_semmaphhoree=CrreatteSeemapphorre(NNULLL,n_Buffferr_orr_Crritiicall,n_Buffferr_orr_Crritiicall, "seemapphorre_ffor_emppty""); h_mmuteex = CrreatteMuutexx(NUULL,FALLSE,"muutexx_foor_uupdaate""); /下下面这个个循环用用线程的的ID号号来为相相应生产产线程的的产品读读写时所所 /使使用的同同步信号号量命名名; forr(j=0;jj<(iint)n_TThreead;j+) sttd:strringg lpp =""semmaphhoree_foor_pprodducee_" innt ttempp =jj; whhilee(teemp) chhar c = (ccharr)(ttempp%100); lpp+=cc; teemp/=100; h_Semmaphhoreej+1=CreeateeSemmaphhoree(NUULL,0,nn_Thhreaad,llp.cc_sttr(); /创创建生产产者和消消费者线线程; forr(i =0;i< (innt) n_TThreead;i+) iff(Thhreaad_IInfooi.enntitty ='PP') hh_Thhreaadii= CreeateeThrreadd(NUULL,0,(LPTTHREEAD_STAART_ROUUTINNE)(Prooducce), &&(Thhreaad_IInfooi),00,NUULL); ellse h_Thrreaddi=CrreatteThhreaad(NNULLL,0,(LPPTHRREADD_STTARTT_ROOUTIINE)(Coonsuume), &(Thrreadd_Innfoi),0,NULLL); /主主程序等等待各个个线程的的动作结结束; waiit_ffor_alll = WaiitFoorMuultiipleeObjjectts(nn_Thhreaad,hh_Thhreaad,TTRUEE,-11); priintff(" n nAALL Prooduccer andd coonsuumerr haave finnishhed theeir worrk. n""); priintff("PPresss aany keyy too quuit!n""); _geetchh(); retturnn 0;/确认认是否还还有对同同一产品品的消费费请求未未执行;booll IffInOOtheerReequeest(intt reeq) forr(innt ii=0;i<nn_Thhreaad;ii+) foor(iint j=00;j<<Thrreadd_Innfoi.n_rrequuestt;j+) iif(TThreead_Inffoii.tthreead_reqquesstjj = rreq) retturnn TRRUE; retturnn FAALSEE;/找出出当前可可以进行行产品生生产的空空缓冲区区位置;int FinndPrroduucePPosiitioon() intt EmmptyyPossitiion; forr (iint i =0;ii<n_Buffferr_orr_Crritiicall;i+) iff(Buuffeer_CCritticaalii = -1) EEmpttyPoosittionn = i; /用下下面这个个特殊值值表示本本缓冲区区正处于于被写状状态; BBufffer_Criiticcali = -2; bbreaak; retturnn EEmpttyPoosittionn;/找出出当前所所需生产产者生产产的产品品的位置置;int FinndBuuffeerPoosittionn(innt PProPPos) intt TeempPPos; forr (iint i =0 ;i<nn_Buuffeer_oor_CCritticaal;ii+) iff(Buuffeer_CCritticaalii=ProoPoss) TTemppPoss = i; bbreaak; retturnn TeempPPos;/生产产者进程程voidd Prroduuce(voiid *p) /局局部变量量声明; DWOORD waiit_ffor_semmaphhoree,waait_forr_muutexx,m_dellay; intt mm_seeriaal;/获得得本线程程的信息息; m_sseriial = (ThhreaadInnfo*)(pp)->seeriaal; m_ddelaay = (DWOORD)(ThrreaddInffo*)(p)->>dellay *INNTE_PERR_SEEC); Sleeep(m_ddelaay); /开开始请求求生产 priintff("PProdduceer %2d sennds thee prroduuce reqquirre.n",m_sseriial); /确确认有空空缓冲区区可供生生产,同同时将空空位置数数emppty减减1;用用于生产产者和消消费者的的同步; waiit_ffor_semmaphhoree = WaaitFForSSinggleOObjeect(emppty_semmaphhoree,-11);/互斥斥访问下下一个可可用于生生产的空空临界区区,实现现写写互互斥; waiit_ffor_muttex = WaiitFoorSiinglleObbjecct(hh_muutexx,-11); intt PProdduceePoss = FinndPrroduucePPosiitioon(); RelleasseMuutexx(h_muttex); /生生产者在在获得自自己的空空位置并并做上标标记后,以以下的写写操作在在生产者者之间可可以并发发; /核核心生产产步骤中中,程序序将生产产者的IID作为为产品编编号放入入,方便便消费者者识别; priintff("PProdduceer %2d beggin too prroduuce at possitiion %2dd.nn",mm_seeriaal,PProdduceePoss); Buffferr_CrritiicallPrroduucePPos = m_sseriial; priintff("PProdduceer %2d finnishh prroduucinng :n ",mm_seeriaal); priintff(" poosittionn %2d :%3d n"" ,PProdduceePoss,Buuffeer_CCritticaalPProdduceePoss); /使使生产者者写的缓缓冲区可可以被多多个消费费者使用用,实现现读写同同步; RelleasseSeemapphorre(hh_Seemapphorremm_seeriaal,n_TThreead,NULLL);/消费费者进程程voidd Coonsuume(voiid * p) /局局部变量量声明; DWOORD waiit_ffor_semmaphhoree,m_dellay; intt m_serriall,m_reqquesstNuum; /消费费者的序序列号和和请求的的数目; intt m_thrreadd_reequeestMAXX_THHREAAD_NNUM;/本消费费线程的的请求队队列; /提提取本线线程的信信息到本本地; m_sseriial = (ThhreaadInnfo*)(pp)->seeriaal; m_ddelaay = (DWOORD)(ThrreaddInffo*)(p)->>dellay *INNTE_PERR_SEEC); m_rrequuesttNumm = (TThreeadIInfoo *)(p)->>n_rrequuestt; forr (iint i = 0;i<mm_reequeestNNum;i+) m_thrreadd_reequeesti = (ThhreaadInnfo*)(pp)->thhreaad_rrequuestti; Sleeep(m_ddelaay); /循循环进行行所需产产品的消消费 forr(i =0;i<mm_reequeestNNum;i+) /请求求消费下下一个产产品 pprinntf("Coonsuumerr %22d rrequuestt too coonsuume %2dd prroduuctn",m_sseriial,m_tthreead_reqquesstii); /如果果对应生生产者没没有生产产,则等等待;如如果生产产了,允允许的消消费者数数目-11;实现现了读写写同步; wwaitt_foor_ssemaaphoore=WaiitFoorSiinglleObbjecct(hh_Seemapphorremm_thhreaad_rrequuestti,-1); /查询询所需产产品放到到缓冲区区的号 iint BuffferrPoss=FiindBBuffferPPosiitioon(mm_thhreaad_rrequuestti); /开始始进行具具体缓冲冲区的消消费处理理,读和和读在该该缓冲区区上仍然然是互斥斥的; /进入入临界区区后执行行消费动动作;并并在完成成此次请请求后,通通知另外外的消费费者本处处请求已已 /经满满足;同同时如果果对应的的产品使使用完毕毕,就做做相应处处理;并并给出相相应动作作的界面面提 /示;该相应应处理指指将相应应缓冲区区清空,并并增加代代表空缓缓冲区的的信号量量; EEnteerCrritiicallSecctioon(&&PC_CriiticcalBuffferrPoss); pprinntf("Coonsuumerr%2dd beeginn too coonsuume %2dd prroduuct n"",m_serriall,m_thrreadd_reequeesti); (TThreeadIInfoo*)(p)->tthreead_reqquesstii =-1; iif(!IfIInOttherrReqquesst(mm_thhreaad_rrequuestti) Buuffeer_CCritticaalBBuffferPPos = -1;/标标记缓冲冲区为空空; prrinttf(""Connsummer%2d finnishh coonsuuminng %2d:n ",mm_seeriaal,mm_thhreaad_rrequuestti); prrinttf("" pposiitioon %2dd :%3dd nn" ,BuffferrPoss,Buuffeer_CCritticaalBBuffferPPos); ReeleaaseSSemaaphoore(emppty_semmaphhoree,1,NULLL); eelseeprinntf("Coonsuumerr %22d ffiniish connsummingg prroduuct %2ddn ",mm_seeriaal,mm_thhreaad_rrequuestti); /离开开临界区区 LLeavveCrritiicallSecctioon(&&PC_CriiticcalBuffferrPoss);