PV操作哲学家问题和生产者-消费者问题剖析_第1页
PV操作哲学家问题和生产者-消费者问题剖析_第2页
PV操作哲学家问题和生产者-消费者问题剖析_第3页
PV操作哲学家问题和生产者-消费者问题剖析_第4页
PV操作哲学家问题和生产者-消费者问题剖析_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、PV操作(哲学家问题)给每个哲学家编号,规定奇数号的哲学家先拿他的左筷子,然后再去拿他的右筷子;而偶 数号的哲学家则相反。这样总可以保证至少有一个哲学家可以进餐。include include include processhinclude include using namespace std;DWORD WINAPI philosopher(LPVOID IpParameter);void thinking(int):void eating(int);void waiting(int);void print(int ,const char *);全局变量CRITICAL_SECTION c

2、rout;/这个变量用来保证输出时不会竟7CRITICAL_SECTION fork5;/定义五个临界变量,代表五更筷J: int main(int argc, char *argv)HANDLE hthread5;int i;int arg5;int count = 5;long a=0;unsigned long retval:InitializeCriticalSection(&crout);初始化临界变量for(i=0;i5;i+)InitializeCriticalSection(fork + i):/创建五个哲学家for(i = 0; i5;i+)argi = i;hthreadi

3、 = CreateThread(NULL, 0, philosopher, (void*) (arg-i), 0, NULL); for(a=0;a30000000;a+);if( hthreadCi = INVALID_HANDLE_VALl:E)/如果线程创建失败返回Tcerr error while create thread i endl;cerr ,zerror code : GetLastError 0 endl;等待所有线程结束retval = WaitForMultipleObjects (5, hthread, true, INFINITE); /等待多个线程 for(a=0

4、;a30000000:a+);if(retval = WAIT.FAILED)cerr wait error, error code: z,GetLastError0endl;for(i = 0; i5;i+)for(a=0;a30000000;a+);i f (C loseHandl e (ht hread i ) = false) /关闭句柄cerr error while close thread iendl;cerr ,zerror code: /zGetLastError0endl;return 0;DWORD WINAPI ph订osopher(LPVOID IpParameter

5、) long a=0;int n = (int *)IpParameter)0;for(a=0;a30000000:a+):print(n, is in!);/srand(time(NULL);while(true)thinking(n); waiting(n); eating(n);print(n, is out!);return n;void thinking(int k)long a=0;for(a=0;a30000000;a+):print (k, is thinking);Sleep (1);/Sleep(rand0 %100) *5);void eating(int k)long

6、a=0;for(a=0;a30000000;a+):print (k, is eating);/Sleep(rand 0%100) *5);Sleep (1);LeaveCriticalSection(fork + (k+l)%5); / /放下右边的筷子/print(k, give left);LeaveCriticalSection(fork + k); /放下左边的筷子/./print (k, give right);void waiting(int k)long a=0;for(a=0;a30000000;a+):print(k, is waiting);Sleep (1);Enter

7、CriticalSection(fork + k) ;/获得左边的筷子/print(k, take left);EnterCriticalSection(fork + (k + 1)%5);/获得右边的筷子/print(k, take right);void print(int who, const char *str)tvpedefint semaphore; /*信号量是一种特殊的整型变量*/semaphore mutex=l; /* 互斥访问 */semaphore emptv=N;/*记录缓冲区中空的槽数*/semaphore fiill=0; /*记录缓冲区中满的槽数*/semaph

8、ore buffN; /*有N个槽数的缓冲区bufN,并实现循环缓冲队列*/ semaphore front=0, rear=0;void p(seniaphore *x) /* p 操作 */ *x=(*x)-l;void v(semaphore *v)/* v 操作 */*y=(*y)+i;void produce_item(int *item_ptr)/*pnntf(Mpioduce ail itemnn);*/*item_ptr=,m,; /* nf is Mmaii 满;*/ void enter_item(mt x)fiont=(fiont+1 )%N;buffront=x;pnn

9、tf(Mentei_item %c to buf%dn, buffront, front);void remove_item(int *yy)reai(reai+l)%N;printfCemovetem %c fiom buff%d, buffieai, rear);*yy=bufrear;buflreai; /* k is nkong 空” */ pnntf(M so the buff%d changed to empty%ciiH, fear, bufrear);void consume_item(mt y)printf(Mcosume tlie item :tlie screem pri

10、nt %cn9 y); void producer(void); void consumer(void);/*生产者*/void producer(void) mt item;wlule(l)produce_item(&item);p(&emptv);/*递减空槽数*/p(&mutex);/*进入临界区*/enter_item(item); /*将一个新的数据项放入缓冲区*/ V(&mutex);/*离开临界区*/v(&hill);/*递增满槽数/if(fiill=N)/*若缓冲区满的话,唤醒消费者进程*/consumerQ;/*消费者*/void consumer(void) mt get_

11、item;wlule(l)p(&fbll);/*递减满槽数*/p(&mutex);/*进入临界区/remove_item(&g亡/*从缓冲区中取走一个数据项*/ v(&mutex);/*离开临界区*/v(&empty);/*递增空槽数*/consume_item(get_item);/*对数据项进行操作(消费)*/ if(empty=N)/*若缓冲区全空的话,唤生产者进程*/pioducerO;/*调用生产者一消费者进程实现进程间同步*/ niaui()producer();return 0;EEE:0Ssample1Debugsample1.execosune the item :the s

12、creen tt*enoueitem m from buf 2 Losume tlie item : tlie screen tt*enoue_iten m from buf 3 cosune the item :the screen tt*enoueitem m from buf4 cosune the item :the screen tt*enoue_iten m from buf 5 cosune the item :the screen tt*enoue_iten m from buf 6 cosune the item :the screen kemoue_item m f i*o

13、m hif T71 cosune the item :the screen tt*enoueitem m from buf 8 cosune the item :the screen tt*enoueitem m from buf 9 cosune the item :the screen 卜emoue_item m from huf0 item to to to to tocosune the enter_item enter_item enter_item enter_item enter_item傲轨拼首丰::the screen buf 1 buf 12 buf L3 bufL4 bu

14、fL4I printnso thebufL2changedtoemptyki printinso thebuf3changedtoemptyki printnso thebuf4changedtoemptyki printnso thebufL5changedtoemptyki printnso thebuf6changedtoemptyki printnso thebufT71changedtoemptyki printnso thebuf8Jchangedtoemptyki printnso thebuf9changedtoemptyki printnso thebuf0changedto

15、emptyki printn生产者消费者问题解决方法二:因为实际情况是生产消费速度不会一致,也不会想方法一一样,消费完后在生产。我们 生产者要保持满足消费者的需求。调整下面的数值,可以发现,当生产者个数多于消费者个 数时,生产速度快,生产者经常等待消费者:反之,消费者经常等待,可以保证消费者可以 一直消费。实现代码:?tinclude #include const unsigned short SIZE_OF_BUFFER = 10; /缓冲区长度unsigned short ProductID = 0;unsigned short ConsumelD = 0;/产品号将被消耗的产品号unsi

16、gned short in = 0;产品进缓冲区时的缓冲区下标unsigned short out = 0;产品出缓冲区时的缓冲区下标int g.bufferSIZE.OF.BUFFER;/缓冲区是个循环队列bool g_continue = true;/控制程序结束HANDLE g_hMutex;/用于线程间的互斥HANDLE g.hFullSemaphore;当缓冲区满时迫使生产考等待HANDLE g.hEmptySemaphore;/当缓冲区空时迫使消费者等待DWORD WINAPI Producer (LPVOID); /生产者线程DWORD WINAPI Consumer (LPVO

17、ID); /消费者线程int mainO创建各个互斥信号g.hMutex = CreateMutex(XULL, FALSE, NULL);g.hFullSemaphore = CreateSemaphore(NULL, SIZE.OF.BUFFER-l, SIZE_OF_BUFFER-1,NULL); g_hEmp15rSemaphore = CreateSemaphore (NULL, 0, SIZE_OF_BUFFER-1, NULL);调整下而的数值,可以发现,当生产者个数多于消费者个数时,/生产速度快,生产者经常等待消费者:反之,消费者经常等待const unsigned short

18、 PRODUCERS.COUNT = 3;/生产者的个数const unsigned short CONSUMERS.COUNT = 1;/消费者的个数总的线程数const unsigned short THREADS.COUNT = PRODUCERS.COUNT+CONSUNERS.COUNT:HANDLE hThreadsPRODUCERS_COUNT; 各线程的handleDWORD producer ID CONSUMERS.COUNT; /生产者线程的标识符DWORD consumer ID THREADS.COUXT: /消费者线程的标识符创建生产者线程for (int i=O;

19、iPRODUCERS_COUNT;+i)hThreadsiJ =CreateThread(NULL, 0, Producer, NULL, 0, &producerIDi);if (hThreadsi=NULL) return -1;创建消费者线程for ( int i=0;iC0NSl3ERS_C0UNT:+i)hThreadsPRODUCERS_COUNT+i=CreateThread(NULL, 0, Consumer, NULL, 0, &consumerIDi);if (hThreadsi=NULL) return -1;while(g_continue) if(getchar()

20、按回车后终止程序运行g_continue = false;return 0;生产一个产品。简单模拟了一下,仅输出新产品的ID号void Produce 0std:cerr Producing +ProductID std:cerr Succeed std:endl;/把新生产的产品放入缓冲区void Append0std:cerr ,zAppending a product g_bufferlinZ = ProductID;in = (in+l)%SIZE_OF_BUFFER;std:cerr Succeed std:endl;/输出缓冲区当前的状态for (int i=O;iSIZE_OF_

21、BUFFER;+i) std:cout i : g_bufferi; if (i=in) std:cout - 生产; if (i=out) std:cout 消费; std:cout std:endl;从缓冲区中取出一个产品void Take 0std:cerr Taking a product ”; ConsumeID = g_bufferout:out = (out+1)%SIZE_OF_BUFFER;std:cerr Succeed std:endl;/输出缓冲区当前的状态for (int i=O;iSIZE_OF_BUFFER;+i) std:cout i : g_bufferi; if (i=in) std:cout - 生产; if (i=out) std:cout 消费; std:cout std:endl:/消耗一个产品voi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论