PV操作(哲学家问题和生产者-消费者问题)(共11页).doc
精选优质文档-倾情为你奉上PV操作(哲学家问题)给每个哲学家编号,规定奇数号的哲学家先拿他的左筷子,然后再去拿他的右筷子;而偶数号的哲学家则相反。这样总可以保证至少有一个哲学家可以进餐。#include <windows.h> #include <iostream> #include <process.h> #include <cstdlib> #include <ctime> using namespace std; DWORD WINAPI philosopher(LPVOID lpParameter); void thinking(int); void eating(int); void waiting(int); void print(int ,const char *); /全局变量 CRITICAL_SECTION crout;/这个变量用来保证输出时不会竞争 CRITICAL_SECTION fork5;/定义五个临界变量,代表五更筷子 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;i<5;i+) InitializeCriticalSection(fork + i); /创建五个哲学家 for(i = 0; i<5;i+) argi = i; hthreadi = CreateThread(NULL, 0, philosopher, (void*)(arg+i), 0, NULL); for(a=0;a<a+); if( hthreadi = INVALID_HANDLE_VALUE)/如果线程创建失败返回-1 cerr << "error while create thread " << i <<endl; cerr << "error code : "<< GetLastError() <<endl; /等待所有线程结束 retval = WaitForMultipleObjects(5,hthread,true,INFINITE);/等待多个线程 for(a=0;a<a+); if(retval = WAIT_FAILED) cerr<< "wait error,error code: "<<GetLastError()<<endl; for(i = 0; i<5;i+) for(a=0;a<a+); if(CloseHandle(hthreadi) = false)/关闭句柄 cerr << "error while close thread " <<i<<endl; cerr << "error code: "<<GetLastError()<<endl; return 0; DWORD WINAPI philosopher(LPVOID lpParameter) long a=0; int n = (int *)lpParameter)0; for(a=0;a<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;a<a+); print(k," is thinking."); Sleep(1); /Sleep(rand() %100) *5); void eating(int k) long a=0;for(a=0;a<a+); print(k," is eating."); /Sleep(rand()%100) *5); Sleep(1); LeaveCriticalSection(fork + (k+1)%5);/放下右边的筷子 /print(k," give left"); LeaveCriticalSection(fork + k);/放下左边的筷子 /print(k," give right"); void waiting(int k) long a=0;for(a=0;a<a+); print(k," is waiting."); Sleep(1); EnterCriticalSection(fork + k);/获得左边的筷子 /print(k," take left"); EnterCriticalSection(fork + (k + 1)%5);/获得右边的筷子 /print(k," take right"); void print(int who,const char *str) long a=0;for(a=0;a<a+); EnterCriticalSection(&crout); cout<<"process "<<who<<str<<endl; LeaveCriticalSection(&crout); 操作截图PV操作(生产者-消费者问题)解决方法一:实现思想,我们在产生足够的产品后,唤醒消费者把生产的产品全部消耗,让后在唤醒生产者生产商品。 /* 用信号量解决生产者消费者问题 */解决方法生产者生产10间产品,唤醒消费者,消费完后,唤醒生产者 #include <STDIO.H> #define N 10 typedef int semaphore; /* 信号量是一种特殊的整型变量 */ semaphore mutex=1; /* 互斥访问 */ semaphore empty=N; /* 记录缓冲区中空的槽数 */ semaphore full=0; /* 记录缓冲区中满的槽数*/ semaphore bufN; /* 有N个槽数的缓冲区bufN,并实现循环缓冲队列 */ semaphore front=0, rear=0; void p(semaphore *x) /* p操作 */ *x=(*x)-1; void v(semaphore *y) /* v操作 */ *y=(*y)+1; void produce_item(int *item_ptr) /*printf("produce an itemn");*/ *item_ptr='m' /* 'm' is "man满" */ void enter_item(int x) front=(front+1)%N; buffront=x; printf("enter_item %c to buf%dn", buffront, front); void remove_item(int *yy) rear=(rear+1)%N; printf("remove_item %c from buf%d", bufrear, rear); *yy=bufrear; bufrear='k' /* 'k' is "kong空" */ printf(" so the buf%d changed to empty-%cn", rear, bufrear); void consume_item(int y) printf("cosume the item :the screem print %cn", y); void producer(void); void consumer(void); /* 生产者 */ void producer(void) int item; while(1) produce_item(&item); p(&empty); /* 递减空槽数 */ p(&mutex); /* 进入临界区 */ enter_item(item); /* 将一个新的数据项放入缓冲区 */ v(&mutex); /* 离开临界区 */ v(&full); /* 递增满槽数 */ if(full=N) /* 若缓冲区满的话,唤醒消费者进程 */ consumer(); /* 消费者 */ void consumer(void) int get_item; while(1) p(&full); /* 递减满槽数 */ p(&mutex); /* 进入临界区 */ remove_item(&get_item); /* 从缓冲区中取走一个数据项 */ v(&mutex); /* 离开临界区 */ v(&empty); /* 递增空槽数 */ consume_item(get_item); /* 对数据项进行操作(消费)*/ if(empty=N) /* 若缓冲区全空的话,唤生产者进程 */ producer(); /* 调用生产者消费者进程实现进程间同步 */ main() producer(); return 0; 生产者消费者问题解决方法二:因为实际情况是生产消费速度不会一致,也不会想方法一一样,消费完后在生产。我们生产者要保持满足消费者的需求。调整下面的数值,可以发现,当生产者个数多于消费者个数时,生产速度快,生产者经常等待消费者;反之,消费者经常等待,可以保证消费者可以一直消费。实现代码:#include <windows.h>#include <iostream>const unsigned short SIZE_OF_BUFFER = 10; /缓冲区长度unsigned short ProductID = 0; /产品号unsigned short ConsumeID = 0; /将被消耗的产品号unsigned 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(LPVOID); /消费者线程int main() /创建各个互斥信号 g_hMutex = CreateMutex(NULL,FALSE,NULL); g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL); g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL); /调整下面的数值,可以发现,当生产者个数多于消费者个数时, /生产速度快,生产者经常等待消费者;反之,消费者经常等待 const unsigned short PRODUCERS_COUNT = 3; /生产者的个数 const unsigned short CONSUMERS_COUNT = 1; /消费者的个数 /总的线程数 const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT; HANDLE hThreadsPRODUCERS_COUNT; /各线程的handle DWORD producerIDCONSUMERS_COUNT; /生产者线程的标识符 DWORD consumerIDTHREADS_COUNT; /消费者线程的标识符 /创建生产者线程 for (int i=0;i<PRODUCERS_COUNT;+i) hThreadsi=CreateThread(NULL,0,Producer,NULL,0,&producerIDi); if (hThreadsi=NULL) return -1; /创建消费者线程 for ( int i=0;i<CONSUMERS_COUNT;+i) hThreadsPRODUCERS_COUNT+i=CreateThread(NULL,0,Consumer,NULL,0,&consumerIDi); if (hThreadsi=NULL) return -1; while(g_continue) if(getchar() /按回车后终止程序运行 g_continue = false; return 0;/生产一个产品。简单模拟了一下,仅输出新产品的ID号void Produce() std:cerr << "Producing " << +ProductID << " . " std:cerr << "Succeed" << std:endl;/把新生产的产品放入缓冲区void Append() std:cerr << "Appending a product . " g_bufferin = ProductID; in = (in+1)%SIZE_OF_BUFFER; std:cerr << "Succeed" << std:endl; /输出缓冲区当前的状态 for (int i=0;i<SIZE_OF_BUFFER;+i) std:cout << i <<": " << g_bufferi; if (i=in) std:cout << " <- 生产" if (i=out) std:cout << " <- 消费" std:cout << std:endl; /从缓冲区中取出一个产品void Take() std:cerr << "Taking a product . " ConsumeID = g_bufferout; out = (out+1)%SIZE_OF_BUFFER; std:cerr << "Succeed" << std:endl; /输出缓冲区当前的状态 for (int i=0;i<SIZE_OF_BUFFER;+i) std:cout << i <<": " << g_bufferi; if (i=in) std:cout << " <- 生产" if (i=out) std:cout << " <- 消费" std:cout << std:endl; /消耗一个产品void Consume() std:cerr << "Consuming " << ConsumeID << " . " std:cerr << "Succeed" << std:endl;/生产者DWORD WINAPI Producer(LPVOID lpPara) while(g_continue) WaitForSingleObject(g_hFullSemaphore,INFINITE); WaitForSingleObject(g_hMutex,INFINITE); Produce(); Append(); Sleep(1500); ReleaseMutex(g_hMutex); ReleaseSemaphore(g_hEmptySemaphore,1,NULL); return 0;/消费者DWORD WINAPI Consumer(LPVOID lpPara) while(g_continue) WaitForSingleObject(g_hEmptySemaphore,INFINITE); WaitForSingleObject(g_hMutex,INFINITE); Take(); Consume(); Sleep(1500); ReleaseMutex(g_hMutex); ReleaseSemaphore(g_hFullSemaphore,1,NULL); return 0;运行结果:专心-专注-专业