系统调用中的信号量PV操作 理发师问题Word文档下载推荐.docx
《系统调用中的信号量PV操作 理发师问题Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《系统调用中的信号量PV操作 理发师问题Word文档下载推荐.docx(19页珍藏版)》请在冰豆网上搜索。
privatestaticintcount=0;
privatestaticSemaphorecustomers=newSemaphore(0,10);
privatestaticintfinish=0;
privatestaticSemaphoremtx=newSemaphore(1,10);
privatestaticintwaiting=0;
//Methods
publicstaticvoidbarber()
while(true)
customers.WaitOne();
mtx.WaitOne();
waiting--;
barbers.Release();
mtx.Release();
cuthair();
finish++;
}
publicstaticvoidcustomer()
count++;
Console.WriteLine("
叮咚!
第{0}个顾客来了"
count);
if(waiting<
chairs)
if(waiting>
0)
此时有{0}个人在等待理发"
waiting);
else
没有人在等待"
);
waiting++;
还有{0}个座位,顾客留下"
(chairs-waiting)+1);
customers.Release();
barbers.WaitOne();
gethaircut();
座位已满,第{0}个顾客离开"
publicstaticvoidcuthair()
开始理发!
这是理发师的第{0}个顾客."
finish+1);
Thread.Sleep(0x2328);
理发完成!
"
publicstaticvoidgethaircut()
Thread.Sleep(0x238c);
第{0}个顾客理发完毕,离开."
finish);
privatestaticvoidMain(string[]args)
stringstr=string.Empty;
请输入椅子的总数目:
chairs=Convert.ToInt32(Console.ReadLine());
理发店共有{0}把椅子"
chairs);
开门接待顾客吗?
Y/N"
for(stringstr2=Console.ReadLine();
(str2!
="
Y"
)&
&
y"
str2=Console.ReadLine())
********对不起,尚未开门!
********"
********营业中,欢迎光临!
newThread(newThreadStart(Program.barber)).Start();
while((str!
(str!
))
Randomrandom=newRandom(DateTime.Now.Millisecond);
Thread.Sleep(random.Next(1,0x2710));
*******************************"
newThread(newThreadStart(Program.customer)).Start();
if((finish>
=10)&
(waiting==0))
已经为{0}个顾客理发了,要关门下班吗?
(Y/N)"
str=Console.ReadLine();
if((str=="
)||(str=="
************暂停营业!
**********"
break;
}
题目:
用多线程同步方法解决睡眠理发师问题(Sleeping-BarberProblem)
理发店有一位理发师,一把理发椅和n把用来等候理发的椅子。
如果没有顾客,则更好师便在理发椅上睡觉,顾客到来时,如理发师闲则理发,否则如有空等候椅则坐等,没有空椅则离开,编写程序实现理发师和顾客程序,实现进程控制,要求不能出现竞争。
2.将1题中问题修改为有两位理发师,设计程序实现同步控制。
问题提示:
可以用一个变量waiting来记录等候理发的顾客数,另使用三个信号量:
用来记录等候理发的顾客数customers;
用来记录理发师是否空闲的信息号量barbers,一个用于互斥访问waiting变量的mutex。
1已经做好了,只是想把理发师扩充问两个,求助!
初始条件:
1.操作系统:
Linux
2.程序设计语言:
C语言
3.设有一个理发师,5把椅子(另外还有一把理发椅),几把椅子可用连续存储单元。
要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
1.技术要求:
1)为每个理发师/顾客产生一个线程,设计正确的同步算法
2)每个顾客进入理发室后,即时显示“Entered”及其线程自定义标识,还同时显示理发室共有几名顾客及其所坐的位置。
3)至少有10个顾客,每人理发至少3秒钟。
4)多个顾客须共享操作函数代码。
2.设计说明书内容要求:
1)设计题目与要求
2)总的设计思想及系统平台、语言、工具等。
3)数据结构与模块说明(功能与流程图)
4)给出用户名、源程序名、目标程序名和源程序及其运行结果。
(要注明存储各个程序及其运行结果的主机IP地址和目录。
)
5)运行结果与运行情况
(提示:
(1)连续存储区可用数组实现。
(2)编译命令可用:
cc-lpthread-o 目标文件名 源文件名
(3)多线程编程方法参见附件。
1设计题目与要求
1.1设计题目
用多线程同步方法解决睡眠理发师问题(Sleeping-BarberProblem)
1.2设计要求
1.2.1初始条件
(1)操作系统:
(2)程序设计语言:
(3)设有一个理发师,5把椅子(另外还有一把理发椅),几把椅子可用连续存储单元。
1.2.2技术要求
(1)为每个理发师/顾客产生一个线程,设计正确的同步算法
(2)每个顾客进入理发室后,即时显示“Entered”及其线程自定义标识,还同时显示理发室共有几名顾客及其所坐的位置。
(3)至少有10个顾客,每人理发至少3秒钟。
(4)多个顾客须共享操作函数代码。
2总体设计思想及开发环境与工具
2.1总体设计思想
2.2多线程编程原理
此次在Linux下进行多线程编程需要用到pthread_create和pthread_join这两个函数。
2.2.1创建一个线程
pthread_create用来创建一个线程,原型为:
externintpthread_create((pthread_t*__thread,__constpthread_attr_t*__attr,void*(*__start_routine)(void*),void*__arg))
第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。
函数thread不需要参数时,最后一个参数设为空指针。
第二个参数设为空指针时,将生成默认属性的线程。
创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。
2.2.2等待一个线程结束
pthread_join用来等待一个线程的结束,函数原型为:
externintpthread_join__P((pthread_t__th,void**__thread_return));
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存
储被等待线程的返回值。
这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被
等待的线程结束为止,当函数返回时,被等待线程的资源被收回。
2.2.3信号量
(1)函数sem_init()用来初始化一个信号量,函数原型为:
externintsem_init__P((sem_t*__sem,int__pshared,unsignedint__value));
sem为指向信号量结构的一个指针;
pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;
value给出了信号量的初始值。
(2)函数sem_post(sem_t*sem)用来增加信号量的值。
当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
(3)函数sem_wait(sem_t*sem)被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。
函数sem_trywait(sem_t*sem)是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。
2.3伪码实现
difinen5;
//为顾客准备的椅子数为5
semaphoremutex=1;
//用于互斥
semaphorecustomers=0;
//等候理发的顾客数
semaphorebarbers=1;
//正在等候顾客的理发师数
intwaiting=0;
//等候理发的顾客数
//理发师线程
voidbarber()
while(true)//判断有无顾客
wait(customers);
//若无顾客,理发师睡眠
wait(mutex);
//互斥
//等候顾客数少一个
signal(mutex);
//释放临界资源
signal(barber);
//理发师去为一个顾客理发
cut_hair;
//正在理发
//顾客线程
voidcustomer()
wait(mutex);
//互斥
if(waiting<
n)//如果有空椅子,则等待
{
waiting++;
//等候顾客数加1
signal(customers);
//如果理发师睡觉,唤醒理发师
wait(barber);
//理发师在理发,顾客等候
get_haircut;
//顾客坐下等理发师
//店里人满了,顾客离开
2.4开发环境与工具
系统平台:
LINUX环境
实现语言:
开发工具:
NANO编辑器
3数据结构与模块说明
3.1数据结构
通过分析课程设计要求,定义以下的数据:
sem_tmutex,customers,barbers;
//designthreesemaphores:
mutex,customer,barbers
intwaiting=0;
//thenumberofwaitingcustomers
intchair[5];
3.2程序模块说明
3.2.1主函数模块
主函数流程图如下:
3.2.2理发师模块
理发师模块函数流程图如下:
3.2.3顾客模块
顾客模块函数流程图如下:
源程序代码
#include<
stdio.h>
stdlib.h>
unistd.h>
pthread.h>
semaphore.h>
fcntl.h>
errno.h>
#definen5//theshophavefivechairs
//designthreesemaphores:
void*barber();
void*customer(void*arg);
intmain(intargc,char*argv[])
//create10semaphoresandoneBarbersemaphore
pthread_tCustomer_id[10],Barber_id;
inti;
sem_init(&
mutex,0,1);
//initmutexsemaphoreto1
customers,0,0);
//initsemaphorecustomersto0
barbers,0,1);
for(i=0;
i<
5;
i++)
pthread_create(&
Barber_id,NULL,(void*)barber,NULL);
for(i=0;
10;
Customer_id[i],NULL,(void*)customer,(void*)(i+1));
pthread_join(Customer_id[i],NULL);
pthread_join(Barber_id,NULL);
return0;
//creatbarberpthread
void*barber()
intnext;
//wait(customers),ifnocustomers,barbersleeping
sem_wait(&
customers);
mutex);
//wait(mutex)
//thenumerofwaitingreduceone
if(chair[i]!
=0)
next=chair[i];
chair[i]=0;
}
printf("
Thebarberiscutting%dthcustomer'
shair\n"
next);
sleep(3);
sem_post(&
barbers);
}
//creatcustomerpthread
void*customer(void*arg)
//wait(mutex)if(waiting<
n)
if(waiting<
//thenumerofwaitingplusone
i++)
if(chair[i]==0)
chair[i]=(int)arg;
***************************************************\n"
Entered:
Number%dcustomercomes,andsitsat%dchair\n"
(int)arg,(i+1));
Thereare%dcustomeronthechair\n"
waiting);
Thecustomers'
locationare:
%d"
chair[i]);
\n"
sleep
(1);
//signal(mutex)
//signal(customers)
//wait(barbers)
Number%dcomes,therearenochairs,thecustomer%disleaving\n"
(int)arg,(int)arg);
5.2.1编辑,编译和运行的过程图
\
5.2.2错误部分截图
5.2.3正确运行结果图
第一次运行结果如下图:
第二次运行结果如下图:
第三次运行结果如下图;
6调试记录
6.1调试记录
周一因有培训与课设时间冲突,故没有上机操作,查阅了相关书籍,并在网上查找了相关资料,了解了linux多线程编程的原理,应注意的问题,及一些常用命令
周二先设计出了该程序的伪代码即其wait、signal操作。
然后,根据其要求进行编程,由于使用的是多线程编程,开始进行编译的时候,编译命令输入错误,没有输入-lpthread,程序总是出现错误。
同时,创建线程函数时,由于对其格式输入错误导致程序无法运行。
例如sb.c,sb1.c等都为本次调试时的程序。
周三主要是不断的调试并完善程序。
程序可以运行,但与要求总有些不符,故不断的进行修改,并对其输出的格式进行完善,使其输出看起来美观一些,容易观察一些。
例如s.c,b.c等程序为此次调试结果。
周四主要是在原有代码的基础上,使程序更完整些。
并进行结果的截图,开始设计并编写课程设计报告。
6.2自我评析和总结
通过本次编程我熟悉了linux下的多线程编程和信号量实现wait、signal操作的全过程,对同步和互斥问题也有了更深一步的理解,同时,也使我对linux编程有了更多的了解,在很多方面,它与在windows下编程有着很大的不同,对与多线程来说更方便一些。
设计过程中也遇到不少困难,尤其是对于多线程的实现,结果总是不如想象中完美。
比如其顾客编号的输出有时会不按顺序,输入有点乱。
另外,有时,输出结束后,程序仍无法结束,必须强制性关闭终端才可以结束程序,这是本程序的一个不足之处。
在本次课程设计中我深深感觉到自己掌握的知识还远远不够,我明白光是知道书本上的知识是远远不够的,一定要把理论知识和实践结合起来。
同时,要多多学习linux的操作。