实验3 报告
时间:2021.02.06 创作:欧阳化 源程序1 /**
作者:wwj
时间:2012/4/12 功能:实现吃水果问题
**题目内容:桌子有一只盘子,只允许放一个水果,父亲专向盘子放苹果,母亲专向盘子放桔子儿子专等吃盘子的桔子,女儿专等吃盘子的苹果。只要盘子为空,父亲或母亲就可以向盘子放水果,仅当盘子有自己需要的水果时,儿子和女儿可从盘子取出。请给出四个人之间的同步关系,并用pv操作实现四个人的正确活动的问题。**
**题目分析:父亲和女儿是相互制约的,父亲进程执行完即往盘中放入苹果后,女儿进程才能执行即吃苹果,是同步关系;
母亲和儿子是相互制约的,母亲进程执行完即往盘中放入桔子,儿子进程才能执行即吃桔子,也是同步关系
而父亲和母亲这两个进程不能同时进行,是互斥关系;** **/
欧阳化创编 2021.02.06
欧阳化创编 2021.02.06
#include HANDLE EmptyPlate; HANDLE Apple; HANDLE orange; HANDLE fatherThread; HANDLE motherThread; HANDLE sonThread; HANDLE daughterThread; //线程函数声明 DWORD WINAPI father(LPVOID IpParameter); DWORD WINAPI mother(LPVOID IpParameter); DWORD WINAPI daughter(LPVOID IpParameter); DWORD WINAPI son(LPVOID IpParameter); int main() { 盘子 Apple = CreateSemaphore(NULL,0,1,NULL); //苹果 欧阳化创编 2021.02.06 //创建信号量 EmptyPlate = CreateSemaphore(NULL,1,1,NULL); // 欧阳化创编 2021.02.06 orange = CreateSemaphore(NULL,0,1,NULL); //桔子 //创建线程 fatherThread CreateThread(NULL,0,father,NULL,0,NULL); motherThread CreateThread(NULL,0,mother,NULL,0,NULL); daughterThread CreateThread(NULL,0,daughter,NULL,0,NULL); sonThread CreateThread(NULL,0,son,NULL,0,NULL); //等线程的结束 WaitForSingleObject(fatherThread,INFINITE); WaitForSingleObject(motherThread,INFINITE); WaitForSingleObject(daughterThread,INFINITE); WaitForSingleObject(sonThread,INFINITE); //关闭线程句柄 CloseHandle(fatherThread); CloseHandle(motherThread); CloseHandle(daughterThread); CloseHandle(sonThread); //关闭信号量句柄 CloseHandle(EmptyPlate); 欧阳化创编 2021.02.06 = = = = 欧阳化创编 2021.02.06 } CloseHandle(Apple); CloseHandle(orange); return 0; //父亲线程函数 DWORD WINAPI father(LPVOID IpParameter) { for(int i = 0; i < 5; ++i){ WaitForSingleObject(EmptyPlate, INFINITE); // P操作 作 } //母亲线程函数 DWORD WINAPI mother(LPVOID IpParmeter) { for(int i = 0; i < 5; ++i){ 欧阳化创编 2021.02.06 // 开始临界区 cout << \"\\nFather往盘中放一个水果\\n\"; // 结束临界区 ReleaseSemaphore(Apple, 1, NULL); // V操 } return 0; 欧阳化创编 2021.02.06 WaitForSingleObject(EmptyPlate, INFINITE); // P操作 作 操作 cout<<\"女儿吃苹果\"< } return 0; } //女儿线程函数 DWORD WINAPI daughter(LPVOID IpParameter) { while(1) { WaitForSingleObject(Apple,INFINITE); //p // 开始临界区 cout << \"\\nMother往盘中放一个桔子\\n\"; // 结束临界区 ReleaseSemaphore(orange, 1, NULL); // V操 //v操作 } return 0; 欧阳化创编 2021.02.06 欧阳化创编 2021.02.06 操作 } //儿子线程函数 DWORD WINAPI son(LPVOID IpParameter) { while(1) { WaitForSingleObject(orange,INFINITE); //p cout<<\"儿子吃苹果\"< //v操作 } } return 0; 程序运行结果截图: 运行结果分析:从运行结果可知父进程执行完后,女儿进程立即执行,这说明父进程跟女儿进程有时序关系,只有当父进程执行之后,女儿进程才会执行,女儿进程是父进程的子线程,他们具有同步关系,同理;母亲进程跟儿子进程,也是同步关系。 源程序2 /** 欧阳化创编 2021.02.06 欧阳化创编 2021.02.06 作者:wwj 时间:2012/4/12 功能:实现生产者和消费者正常活动 题目内容:生产者-消费者问题,是指两组进程共享一个环形的缓冲区。一组进程被称为生产者,另一组进程被称为消费者。 缓冲池是由若干个(程序假设为4个)大小相等的缓冲区组成的,每个缓冲区可以容纳一个产品。生产者进程不断地将生产的产品放入缓冲池, 消费者进程不断地将产品从缓冲池取出。用PV操作实现生产者和消费者的正常活动的程序 题目分析: 在生产者-消费者问题中,既存在进程同步问题,也存 在着临界区的互斥问题。当缓冲区都满时,表示供大于求, 生产者停止生产,进入等待状态,同时唤醒消费者;当缓冲区都空时,表示供不应求,消费者停止消费,唤醒生产者。 这说明了,生产者和消费者存在同步关系。 对于缓冲池,它显然是一个临界资源,所有的生产者 和消费者都要使用它, 而且都要改变它的状态,故对于缓冲池的操作必须是互斥 欧阳化创编 2021.02.06 欧阳化创编 2021.02.06 的。 */ #include //i和j分别指向缓冲区 int buffer[n]; //缓冲池 int ItemP=0; //用来存放生产的产品 int ItemC=0; //用来存放消费的产品 //声明句柄 HANDLE mutex; HANDLE empty; //缓冲池信号量 //空缓冲区信号量 HANDLE full; //满缓冲区信号量 HANDLE pThread; //producer线程句柄 HANDLE cThread; //consumer线程句柄 //声明进程函数 DWORD WINAPI producer(LPVOID IpParameter); DWORD WINAPI consumer(LPVOID IpParameter); int main() { 欧阳化创编 2021.02.06 欧阳化创编 2021.02.06 //创建信号量 mutex = CreateSemaphore(NULL,1,1,NULL); empty = CreateSemaphore(NULL,1,4,NULL); full = CreateSemaphore(NULL,0,4,NULL); cout<<\"市场运作开始。。。。。\"< CreateThread(NULL,0,producer,NULL,0,NULL); cThread CreateThread(NULL,0,consumer,NULL,0,NULL); //等待相应线程结束 WaitForSingleObject(pThread,INFINITE); WaitForSingleObject(cThread,INFINITE); //关闭线程句柄 CloseHandle(pThread); CloseHandle(cThread); //关闭信号量句柄 CloseHandle(mutex); CloseHandle(empty); CloseHandle(full); cout<<\"整个市场运营结束。。。。\"< 欧阳化创编 2021.02.06 = = 欧阳化创编 2021.02.06 } //producer线程函数的定义 DWORD WINAPI producer(LPVOID IpParameter) { for(int k=0;k<5;k++) { cout<<\"\\nproducer 生产一个产品 \"< ItemP=ItemP+1; //增加一个 //P操作 WaitForSingleObject(mutex,INFINITE); cout<<\"\\n把一个产品放入了一个空的缓 冲区\"< buffer[i]=ItemP; //将产品放入缓冲 ReleaseSemaphore(mutex,1,NULL); //V操作 } 欧阳化创编 2021.02.06 ReleaseSemaphore(full,1,NULL); 欧阳化创编 2021.02.06 作 } return 0; DWORD WINAPI consumer(LPVOID IpParameter) { for(int k=0;k<5;k++) { WaitForSingleObject(full,INFINITE); //P 操 WaitForSingleObject(mutex,INFINITE); ItemC=buffer[j]; //将缓冲区里的产 品取出,放入消费产品里头 j=(j+1)%n; //j指向下一 个满的缓冲区 产品 } 欧阳化创编 2021.02.06 ReleaseSemaphore(mutex,1,NULL); //V操作 ReleaseSemaphore(empty,1,NULL); cout<<\"\\n消费者消费一个产品\"< } return 0; 欧阳化创编 2021.02.06 程序运行截图如下: 运行结果分析:从运行结果来看,整个市场运作有两种状态, 一种状态是生产着连续生产两个产品,每生产一个产品后,立马把产品产品放入缓冲区,接着消费者消费产品;另一种状态是消费者先把缓冲区里面的产品消费,然后生产者把已经生产的产品放入缓冲区里;生产者和消费者即存在同步关系,又存在互斥关系,只是相对而言的,对于缓冲区来说,当缓冲区满的时候,只能由消费者消费产品,接着生产者才能把产品放入缓冲区;当缓冲区为空时,只能由生产者生产产品并把产品放入缓冲区,接着消费者才能消费产品;这两种关系都属于同步关系;对于缓冲池来说,缓冲池只有一个,生产者和消费者只能有一个使用它,并且他们不存在时序关系,到底是谁先使用,只能靠市场的调度和控制。 时间:2021.02.06 创作:欧阳化 欧阳化创编 2021.02.06 因篇幅问题不能全部显示,请点此查看更多更全内容