第一篇:售票员和汽车司机的进程同步问题
计算机操作系统实验报告
一、实验名称:售票员和汽车司机的进程同步问题
二、实验内容:创建两个进程模拟售票员和汽车司机的同步行为。具体内容如下:
1.司机的活动:启动车辆,正常行车,到站停车。2.售票员活动:关车门,售票,开车门。
3.当发车时间到,售票员关好车门后,司机才能启动车辆,售票员才开始售票。当到站时,司机停稳车后,售票员才能打开车门,车上乘客先下车,然后站牌乘客上车。
三、问题分析与设计
分析:司机与售票员要协同工作:一方面只有售票员把门关好之后司机才可开车,因此售票员关好门之后要通知司机开车,然后售票;另一方面,也只有司机把车停下之后售票员才能开门让乘客下车和上车,因此,此时司机应通知售票员。汽车当前正在始发站停车让乘客让乘客上车,因此,必须设置一定的信号量来实现他们之间的同步问题。
设计:设置司机与售票员的信号量为全局变量,并且客车的人数:现在人数、下车人数、上车人数为全局变量;设置司机与售票员的线程。考虑到第一站和最后一站的问题,应单独处理,故在各自的线程中分情况讨论:
具体的思路是下面的图示。其中S1是司机的信号量,S2是售票员的信号量。
程序的实现(代码): #include
int Recent_num=0;//某一时刻的客车上的人数 int Get_on_num;//上车的人数 int Get_off_num;//下车的人数 int pork=1;//客车到达路线的站数 HANDLE Semaphore_driver;//Driver的信号量 HANDLE Semaphore_conductor;//Conductor的信号量 //产生一定范围的随机数,可避免下面程序的判断是否超出客车的最大容量问题
int Get_random(int min,int max){ int a;srand((int)time(0));while(1){ a=rand()%(Total_num+1);if(a>=min && a<=max)return a;} } //Driver的线程
DWORD WINAPI Thread_Driver(LPVOID Driver){ while(pork<=Total_num){ if(pork==Total_pork){ WaitForSingleObject(Semaphore_driver,INFINITE);printf(“终点站到了,谢谢乘坐该公交车,祝您愉快!n”);printf(“到达终点站时汽车上还有 %d 人。n”,Recent_num);ReleaseSemaphore(Semaphore_conductor,1,NULL);return 0;} else { if(pork==1)printf(“发车时间到,现在是第 %d 站n”,pork);else printf(“ %d 站到了n”,pork);if(pork!=1)printf(“司机已停车。n”);
ReleaseSemaphore(Semaphore_conductor,1,NULL);// 增加信号量
WaitForSingleObject(Semaphore_driver,INFINITE);printf(“已关门,汽车开始行使。n”);ReleaseSemaphore(Semaphore_conductor,1,NULL);} Sleep(1000);} return 0;} //Conductor的线程
DWORD WINAPI Thread_Conductor(LPVOID Conductor){ while(1){ if(pork < Total_pork){
WaitForSingleObject(Semaphore_conductor,INFINITE);if(pork==1){
Get_on_num=Get_random(0,Total_num-Recent_num);printf(“ %d 人已经从该站上车。n”,Get_on_num);Recent_num+=Get_on_num;} else { printf(“售票员请开门让乘客上下车!n”);Get_off_num=Get_random(0,Recent_num);printf(“%d人从第 %d 站下车。n”,Get_off_num,pork);Sleep(1000);//避免了时间的问题带来的不是随机数的现象
Recent_num-=Get_off_num;Get_on_num=Get_random(0,Total_num-Recent_num);printf(“%d人从该第 %d 站上车。n”,Get_on_num,pork);Recent_num+=Get_on_num;} printf(“此时车上共有:%d人n”,Recent_num);printf(“上车或下车完毕,售票员请关门!n”);ReleaseSemaphore(Semaphore_driver,1,NULL);
WaitForSingleObject(Semaphore_conductor,INFINITE);printf(“现在售票员开始售票。n”);printf(“nnnn”);pork++;} if(pork==Total_pork){ ReleaseSemaphore(Semaphore_driver,1,NULL);
WaitForSingleObject(Semaphore_conductor,INFINITE);printf(“售票员请开门让乘客下车!n”);return 0;} Sleep(1000);} return 0;} //主函数 int main(){ HANDLE Driver;HANDLE Conductor;
Semaphore_driver=CreateSemaphore(NULL,0,1,“semaphore_driver”);//创建Driver的信号量
Semaphore_conductor=CreateSemaphore(NULL,0,1,“semaphore_conductor”);//创建Conductor的信号量
Driver=CreateThread(NULL,0,Thread_Driver,&Driver,0,NULL);//创建Driver的线程
Conductor=CreateThread(NULL,0,Thread_Conductor,&Conductor,0,NULL);//创建Conductor的线程
CloseHandle(Driver);//关闭Driver的线程 CloseHandle(Conductor);//关闭Conductor的线程 //GetLastError();while(1);system(“pause”);return 0;}
程序执行结果:
实验心得与反思:
通过本次实验,加深了我们对进程同步与互斥的理解,而且懂WaitForSingleObject函数的作用,它相当于P操作;而ReleaseSemaphore函数相当于V操作,用这两个函数来实现P,V操作,以改变信号量的值,从而实现进程同步。实验过程中,我们发现以下是我们应该反思的:
1:线程的创建的函数的参数的理解还不太懂,主要是没学过,对于其中的一些调用函数不太懂里面的意思。
2:线程的设计要考虑到各个情况,第一站和最后一战,还有其中的全局的变量的运算的放到的是售票员的线程中,也就是其中的一些操作的位置问题,要考虑到同步的两个线程之间的关系。3:关于信号量的问题,其要的是全局变量。
4:最最重要的是一些Win32 API 中的库函数有关线程的创建等的理解,对其中的函数参量的理解有待进一步学习理解。
09信管(2)班
何美西 109253030212 樊丽彬 109253030215 孔娜 109253030218
第二篇:司机与售票员原创 完整代码
自己写的:(功能感觉达到我要目的,感觉没有把操作量层次写出来,大家参考学习)
#include
#define max 80//假设汽车的最大容量为80 int num=0;//初始还没有启动客车上的人数为0 int sc=0;//上车的人数 int xc=0;//下车的人数
int k;//上车-下车,停站上下车后后人数变化,即净上车人数;
//k=sc-xc;//净上车人数/
int dr();int cd();
int check(){
if(sc==-1||xc==-1)
{cout<<“旅途愉快,汽车到达总站,再见”< exit(1); } return 0;} int dr()//司机driver的信号量 { //num=num+k;if(num<=max){ cout<<“汽车关门准备开车!”< } cout<<“司机开车!”< int c,sji;//超载人数/实际上车人数 k=sc-xc;//净上车人数/ num=num+k;//上下乘客后车上人数 if(num<=max) { cout<<“现在车上人数为:”< cout<<“坐好扶稳!”< cout<<“===================================”< cout<<“===================================”< cout<<“===================================”< } if(num>max) { c=num-max;sji=sc-c; cout<<“超载”< num=max;cout<<“已下”< } return 0;} /*主函数*/ int main(){ cout<<“=========欢迎使用司机与售票员信息量同步公交车系统=============”< cout<<“请输入上车人数!”< while(num>max) { cout<<“警告:输入上车人数后,人数已经超过限载人数,输入错误请重新输入”< cout<<“重新输入上车人数为:”< cin>>sc; num=sc; check(); } cout<<“第一次启动上车人数为”< check(); while(sc!=-1||xc!=-1) { cout<<“汽车行驶中.......!”< cout<<“请输入下车人数!”< check(); while(xc>num) { cout<<“输入下车人数超过车上人数,输入错误,请重新输入”< cout<<“重新输入下车人数为:”< cin>>xc; check(); } cout<<“请输入上车人数!”< //cout<<“上车人数为”< check();if(num>max) { cout<<“警告:输入上车人数后车里人数已经超过车的限载人数”< } //num=num+sc-xc;//上下乘客后车上人数 //cout<<“车上人数总共为”< dr(); } return 0;} 网上下载的:好像作者上传缺少311.h头文件 #include using namespace std; HANDLE Semaphore_dirver;//司机信号量的句柄 HANDLE Semaphore_condutor;//售票员信号量的句柄 int num_station=0; //司机进程 void Thread_Driver(){ while(true) { if(WaitForSingleObject(Semaphore_dirver,INFINITE)==WAIT_OBJECT_0)//相当与P(Semaphore_dirver)操作 {cout<<“汽车行驶中,请您扶稳坐好!”< Sleep(5000);//行车时间 } ReleaseSemaphore(Semaphore_condutor, 1, NULL);//相当与V(Semaphore_condutor)操作提醒售票员可以售票了 } } //售票员进程 void Thread_Conductor(){ while(true) { if(WaitForSingleObject(Semaphore_condutor,INFINITE)==WAIT_OBJECT_0)//判断车是否已停 if(!num_station) //第一站 {cout<<“没人下车”< num_station++; NUM_ON=random_num(NUM_MAX); Sleep(3000);//乘客上车时间 cout< NUM_CURRENT=NUM_ON+NUM_INITIAL;//起始站上车的人数 } else { cout<<“车辆进站,请您注意安全!开门请当心,下车请走好!下车后请勿从车前绕行!”< Sleep(3000);//乘客下车时间 NUM_DOWN=random_num(NUM_CURRENT);//下车人数 cout< NUM_CURRENT=NUM_CURRENT-NUM_DOWN;//下车后的人数 if(NUM_CURRENT { cout<<“311路无人售票车开往南门,请您按顺序投币上车!”< cout<<“上车的乘客请从后门移动,准备下车!”< Sleep(3000);//乘客上车时间 NUM_ON=random_num(NUM_MAX-NUM_CURRENT);//上车人数 cout< NUM_CURRENT=NUM_CURRENT+NUM_ON;//上车后人数 cout<<“车上有”< } else cout<<“座位已满,请等下一辆!”< } ReleaseSemaphore(Semaphore_dirver,1,NULL);//让司机开车的信号 } } /*主函数*/ int main(){ HANDLE thread[2];//定义两个线程句柄 Semaphore_dirver = CreateSemaphore(NULL,1, 1, NULL);//司机信号量 Semaphore_condutor = CreateSemaphore(NULL, 0, 1, NULL);//售票员信号量 DWORD threadID[2]; thread[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Thread_Driver),NULL,0,&threadID[0]);//司机进程 thread[1]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Thread_Conductor),NULL,0,&threadID[1]);//售票员进程 WaitForMultipleObjects(1, thread, TRUE, INFINITE);//等待两个线程结束 return 0;} 汽车售票员阿姨 今年暑假,妈妈带我去温州小姑家做客。 一路上,车子轻快地奔驰着,窗外风景优美,山上绿树成荫,绿油油的小草仿佛给山上铺上一层厚厚的毛毯。在车上,我和妈妈有说有笑。我一边喝着尖叫的饮料,一边唱着欢快的歌曲。突然一个急刹车,我一阵恶心,急忙对妈妈说:妈妈很想吐。妈妈连忙蹲下拿塑料袋,可我哗一下全吐在了妈妈身上。全车人都回过头来捂着嘴看着妈妈,妈妈狼狈不堪。正在这时,售票员阿姨毫不犹豫的拿来纸巾,一边替我擦拭吐在身上的脏物,一边安慰说:别急,别急,你等会会好的。还倒开水给我喝,过了一会儿我舒服多了,不知不觉中我在妈妈的怀里睡着了。 当我再醒来的时候,车子停住了。我特意去看了看了那位阿姨。她秀丽端庄,和蔼可亲,嘴角上堆满笑容。你看,她又在忙着扶一位白发苍苍的老奶奶上车,帮助上下车的乘客拿行李。这就是汽车售票员阿姨。 操作系统:用多线程模拟汽车司机与售票员需求分析试验报告 本实验利用多线程模拟汽车司机与售票员之间的协同工作即同步过程。一方面只有售票员把车门关好了司机才能开车,因此,售票员关好车门应通知司机开车;另一方面,只有汽车已经停下,售票员才能开门上下客,故司机停车后应通知售票员。实验的结果是在屏幕显示二者的同步过程。 一、设计过程 基本原理:在Windows的一个进程内包含一个或多个线程,32位Windows环境下的WIN32 API提供了多线程应用程序开发所需的接口函数,本实验就是C++语言编写的WIN32 API的多线程编程。具体过程: 1.创建两个信号对象,设定初始值; 2.创建两个子线程函数,一个为司机的操作过程,一个为售票员的操作过程。我们在这里设定站点数为10个;在司机操作的子线程中,用一个while循环,当到最后一站时,就退出,此时,程序运行结束。3.编写主线程函数,在其中调用两个子线程。 二、源代码 #include HANDLE hSemaphore1=CreateSemaphore(NULL, 0, 1, NULL);HANDLE hSemaphore2=CreateSemaphore(NULL, 0, 1, NULL); int station=1; DWORD WINAPI ThreadDriver(LPVOID LpParameter){ while(station<=10){ cout<<“司机正常行车”< cout<<“前方为”< if(station==10) { cout<<“终点站到了”< return 0; } cout<<“到达”< ReleaseSemaphore(hSemaphore2,1,NULL); WaitForSingleObject(hSemaphore1,INFINITE); cout<<“离站开车”< Sleep(500); station++;} return 0;} DWORD WINAPI ThreadConductor(LPVOID LpParameter){ while(1){ WaitForSingleObject(hSemaphore2,INFINITE); cout<<“售票员开门”< cout<<“售票员关门”< cout<<“售票员向刚上车售票”< ReleaseSemaphore(hSemaphore1,1,NULL); Sleep(1000); } return 0;} int main(){ HANDLE hDriver;HANDLE hConductor;cout<<“多线程模拟司机售票员同步过程n”;cout<<“----------------------------n”; hDriver=CreateThread(NULL,0,ThreadDriver,NULL,0,NULL);Sleep(10);hConductor=CreateThread(NULL,0,ThreadConductor,NULL,0,NULL);Sleep(300000);CloseHandle(hDriver);CloseHandle(hConductor);return 0;} 三、运行结果: 多线程模拟司机售票员同步过程----------------------------司机正常行车 前方为1站点 到达1站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为2站点 到达2站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为3站点 到达3站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为4站点 到达4站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为5站点 到达5站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为6站点 到达6站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为7站点 到达7站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为8站点 到达8站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为9站点 到达9站点 售票员开门 乘客正在上车 售票员关门 售票员向刚上车售票 离站开车 司机正常行车 前方为10站点 终点站到了 四、程序结果分析 从运行结果看,基本上模拟了司机和售票员的同步过程。此程序简单的实现了线程间的同步过程,即运用win32提供的接口函数,主要是CreateThread,WaitForSingleObject,ReleaseSemaphore这几个函数实现主要功能。 程序还有很多欠缺,需要做进一步的改进。比如可以实际线路的同步过程,考虑司机与售票员同步过程中的更多现实因素,比如,提供站点时间、上下车人数等等,将其运用到实际当中去。 计算机操作系统实验报告 -------售票员和汽车司机的进程同步问题 一、设计分析 司机与售票员要协同工作:一方面只有售票员把门关好之后司机才能开车,因此售票员关好门之后要通知司机开车;另一方面,也只有司机把车停下之后售票员才能开门让乘客下车和上车,此时司机应通知售票员。汽车当前正在始发站停车让乘客上车。因此,必须设置一定的信号量来实现他们之间的同步问题。 把司机与售票员的信号量设置为全局变量,并把客车上的人数:现在人数、下车人数、上车人数设置为全局变量;设置司机与售票员各自的线程。考虑到第一站和最后一站的问题,应单独处理,故在各自的线程中分情况讨论: 由于下车的人数是随机的,设计时考虑到了人数可能会超过客车的最大上限的问题。具体的思路是下面的图示。 二、算法实现(源代码) #include //假设汽车的最大容量为88 #define total_pork 9 //总的站数 int recent_num=0; //某一时刻的客车上的人数 int get_on_num; //上车的人数 int get_off_num; //下车的人数 int pork=1; //赋初始值 HANDLE SJ; //司机的信号量 HANDLE SPY; //售票员的信号量 int Get_random(int min, int max) //产生一定范围的随机数,可避免下面程序的判断超出客车的最大容量问题{ int a;srand((int)time(0)); while(1){ a=rand()%(total_num+1);if(a>=min && a<=max)return a;} } //司机的线程 DWORD WINAPI Thread_Driver(LPVOID Driver){ while(pork<=total_num){ if(pork==total_pork){ WaitForSingleObject(SJ,INFINITE);cout<<“到达总站,欢迎您下次乘坐**路公交车”< { ReleaseSemaphore(SPY,1, NULL);WaitForSingleObject(SJ,INFINITE);cout<<“汽车启动”< } Sleep(1000);} return 0;} //售票员的线程 DWORD WINAPI Thread_Conductor(LPVOID SPY){ while(1){ if(pork cout<<“这是第”< WaitForSingleObject(SPY,INFINITE);if(pork==1){ cout<<“SPY开始售票”< get_on_num=Get_random(0,total_num-recent_num); cout< recent_num+=get_on_num;cout<<“共有”< { cout<<“SJ停好车,乘客开始上下车”< get_off_num=Get_random(0,recent_num); cout< return 0;} //主函数 int main(){ HANDLE SJ;HANDLE SPY;SJ=CreateSemaphore(NULL,0,1,“semaphore_driver”);//创建司机的信号量 SPY=CreateSemaphore(NULL,0,1,“semaphore_conductor”);//创建售票员的信号量 SJ=CreateThread(NULL,0,Thread_Driver,&SJ,0,NULL);//创建司机的线程 SPY=CreateThread(NULL,0,Thread_Conductor,&SPY,0,NULL);//创建售票员的线程 CloseHandle(SJ);CloseHandle(SPY);while(1);system(“pause”);return 0;} 三.实现结果 四、心得体会 1、因为司机与售票员是两条单独处理的线程。程序先对司机的线程进行设计,接着再进行售票员的线程设计。因为两者是需要相互协调,又先后顺序的,所以编起程序来比较复杂,而且很乱,尤其对于第一次接触的我们而言。 2、上下车的人数是随机的,所以,我们在编程序时必须注意使程序能够判断所出现的随机数在汽车可以承载的最大容量之内。 3、C++语言基础不是很好,所以编起程序来比较费力,这种设计性的实验对于我们而言还是有一定的难度的,所以部分程序是参照网上的类似程序。第三篇:汽车售票员阿姨
第四篇:用多线程模拟汽车司机与售票员需求分析试验报告
第五篇:计算机操作系统-司机与售票员的进程问题-实验报告