进程之间的同步互斥与通信理发师问题操作系统课程设计

合集下载

进程之间的同步互斥与通信理发师问题操作系统

进程之间的同步互斥与通信理发师问题操作系统

操作系统课程设计目录1. 课程设计目的 (3)2. 设计要求 (3)3. 问题具体描述 (3)4. 设计分析 (3)5. 设计分工 (4)6. 数据结构说明 (4)7. 系统结构说明 (4)8. 系统调用说明 (4)9. 分工设计说明 (5)10. 算法流程图 (5)11. 分工代码 (6)12. 整体代码 (7)13. 程序运行 (10)14. 总结 (11)1.课程设计目的1.内容围绕操作系统原理中最重要的基本概念和基本原理展开2.巩固对原理知识的学习效果3.加深对基本概念的理解4.学习如何将基本原理和实际设计、应用有机结合5.锻炼本专业的基本能力2.设计要求1:进程间通信、并发(同步/互斥)、文件读写2:内存管理、Dll、Windows消息机制、IO (尚未最终定型)3.问题具体描述1.完成N个生产者和M个消费者之间的并发控制,N、M不低于5,数据发送和接收缓冲区大小不小于10个。

2.某个生产者进程生产的消息供K个消费者进程消费。

K《=M。

某些消费进程消费多个生产者生产的消息。

生产者和消费者之间的对应关系可以在程序开始有一个文件中读入,也可以动态调整。

3.每个生产进程生产M个消息后结束运行。

如果一个消费者进程没有对应的生产者进程在运行后,也结束运行。

4.设计分析课程设计的主要目的是了解并且掌握进程之间的同步互斥,和进程之间的通信问题。

结合课本上的生产者与消费者问题可以从这方面来实现一个多进程的小系统,并且解决多个进程之间的通信,并发等问题,以此来达到课程设计的目的。

理发师问题是将顾客看做生产者,将理发师作为消费者。

设置一定数量的椅子的数目来作为缓存区的大小。

顾客来到的时候坐在椅子上,将自己作为“产品”,理发师理发的时候从椅子上叫走顾客,相当于消费“产品”,从而达到了课程设计要求的前一个要求。

顾客作为生产者,每到来一个就使计数器count增加1,以便让理发师理发(相当于消费)至最后一个顾客(相当于产品)。

计算机操作系统进程的互斥及同步PPT学习教案

计算机操作系统进程的互斥及同步PPT学习教案
进程在进入临界区之前,执行P操作(申请资源) 进程在退出临界区之后,执行V操作(归还资源)
第31页/共49页
பைடு நூலகம்
第32页
3.6 进程同步
3.6.1. 同步的概念
互斥的概念来自于诸进程对独占使用资源(设备)的竞 争,同步来源于多个进程的合作。在人类社会中竞争与 合作是永恒的。
同步:所谓同步就是并发进程在一些关键点上可能需要 相互等待与互通消息,这样的相互制约关系称为进程同 步。
2021/7/18
第13页/共49页
第14页
2. 间接制约
间接制约:把由于共享某一公有资 源而引起的在临界区内不允许并发 进程交叉执行的现象,称为由共享 公有资源而造成的对并发进程执行 速度的间接制约
直接制约:一组在异步环境下的并 发进程,各自的第14页执/共4行9页 结果互为对方
2021/7/18
第15页
3.互斥
定义: 一组并发进程中的一个或多个程序段,因共享
某一公有资源而导致它们必须以一个不允许交叉执 行的单位执行。也就是说,不允许两个以上的共享 该资源的并发进程同时进入临界区称为互斥。
一般情况下,作为程序段的一个过程不允许多 个进程共同访问它。
2021/7/18
第15页/共49页
第16页
生产者消费 者1.exe
第7页/共49页
生产者进程
while (true) {
/* produce an item and put in nextProduced */ while (count == BUFFER_SIZE)
; // do nothing buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count ++; }

OS-04进程同步互斥与通信

OS-04进程同步互斥与通信

4.1并发进程
• 前趋图的例子
– P1→P2,P1→P3,P1→P4,P2→P5, P3→P5,P4→P5,P4→P6,P5→P7, P6→P7
2
5 1 3 6 4 7
§4.1并发进程
操作系统设计中的核心问题是关于进程和线程的管 理
– 多道程序技术 管理单处理器系统中的多个进程 – 多处理技术 个进程的执行 管理多处理器系统中的多个进程
进程同步与互斥
互斥:软件方法
Peterson算法
Dekker算法 Lamport面包店算法 Eisenberg/Mcguire算法
进程同步与互斥
互斥:硬件的支持
中断禁用 在单处理器机器中,并发进程不能重叠,只能交
替。此外,一个进程将一直运行,直到它调用了一个操 作系统服务或被中断。因此,为保证互斥,只需要保证 一个进程不被中断就可以 当一个计算机系统包括多个处理器时,在这种情况下,

第一个字符丢失,第2个字符被显示了两次
P1
getchar() chin chout ?
P2
X
Y X Y
Y
Y
Y
putchar() putchar() echo
与时间有关的错误
错误原因之1:
进程执行交叉; 错误原因之2:
涉及公共变量(chin和chout)。
与时间有关的错误
void echo() { chin = getchar() ; chout = do(chin); putchar(chout) ; }
信号量机制
信号量(semaphore):一个与资源有关的,初
值为非负数的整型变量称为信号量。用S表示,初
值和资源有关

操作系统同步与互斥浅谈

操作系统同步与互斥浅谈

操作系统同步与互斥浅谈——基于经典案例“理发师问题”摘要:并发是所有问题的基础,也是操作系统设计的基础。

并发包括很多设计问题,其中有进程中的通信、资源共享和竞争、多个进程活动的同步以及分配给进程的处理器时间等。

本文围绕经典操作系统案例“理发师问题”介绍并发中同步与互斥的基本概念和多个进程并发执行的简单案例,重点介绍信号量与消息传递机制。

关键字:操作系统并发同步互斥理发师问题Abstract:Concurrency is the basis of not only all the problems, but also the operating system design. Complicated, it includes many design issues, about the process of communication, resource sharing and competition, the activities of multiple processes simultaneously and the allocation of processor time to the process. This article describes the basic concepts of concurrency and the simple case of concurrent execution of multiple processes around the classic case of "Sweeney problem ", focusing on semaphores and message passing.Key word:Operating system Concurrency Synchronization mutual exclusion Sweeney problem 1.进程间怎么通信?——并发的基本知识1.1 进程间进行通信的原因进程是多用户、多任务操作系统必不可少的基本功能和基础设施。

操作系统实验五 理发师问题

操作系统实验五 理发师问题

实验题目:理发师问问题学号:201000130133 班级: 2010级计算机4班姓名:郑思雨 Email:1412561943@实验目的:1、进一步研究和实践操作系统中关于并发进程同步与互斥操作的一些经典问题的解法。

2、加深对于非对称性互斥问题有关概念的理解。

观察和体验非对称性互斥问题的并发控制方法。

3、进一步了解Linux系统中IPC进程同步工具的用法,训练解决对该类问题的实际编程、调试和分析问题的能力。

硬件环境:微机(多核,4GB 以上内存,320GB 以上硬盘)软件环境:Ubuntu-Linux 操作系统Gnome 桌面gcc version 4.1.2gedit 2.18.2OpenOffice 2.3实验步骤:1、了解实验的目的,了解并掌握与进程间通信IPC中的3个对象:共享内存、信号灯数组、消息队列到呢个有关的系统调用,并能熟练的掌握。

2、阅读实验题目并分析实验的需求。

理发店问题:假设理发店的理发室中有3个理发椅子和3个理发师,有一个可容纳4个顾客坐等理发的沙发。

此外还有一间等候室,可容纳13位顾客等候进入理发室。

顾客如果发现理发店中顾客已满(超过20人),就不进入理发店。

在理发店内,理发师一旦有空就为坐在沙发上等待时间最长的顾客理发,同时空出的沙发让在等候室中等待时间最长的的顾客就坐。

顾客理完发后,可向任何一位理发师付款。

但理发店只有一本现金登记册,在任一时刻只能记录一个顾客的付款。

理发师在没有顾客的时候就坐在理发椅子上睡眠。

理发师的时间就用在理发、收款、睡眠上。

(1)首先创建ipc.h文件,在里面定义生产者/消费者共用的IPC函数的原型和变量。

(2)然后创建ipc.c文件,在里面定义生产者/消费者共用的IPC 的具体的相应函数。

(3)创建sofa_control文件,在里面声明两个消息队列,当沙发空闲时则会将空闲的消息放入相应的队列中,让顾客可以进入沙发中,当理发师空闲时,也会将相应的消息放入队列中,从而可以让顾客到理发椅上进行理发。

系统调用中的信号量PV操作 理发师问题

系统调用中的信号量PV操作 理发师问题

⏹理发师问题:一个理发店由一间等候室W和一间工作室B组成。

顾客可以从外面大街上进入W等候理发。

两个房间的入口是并排的,且共享一扇日本式可滑动的推拉门(门总是挡住一个入口)。

顾客在工作室内理完发,可由B 的旁门出去。

W中有N把椅子,顾客必须坐着等候。

理发师可由门上小窗查看W中无人就睡觉,否则开门,并叫一位顾客入内理发。

顾客每进入一位,都拉铃通知理发师。

若把顾客和理发师都视为进程,请用P、V操作写出进程的同步算法。

⏹要求打印:题目中要求描述理发师和顾客的行为,因此需要两类线程barber()和customer ()分别描述理发师和顾客的行为。

其中,理发师有活动有理发和睡觉两个事件;等待和理发二个事件。

店里有固定的椅子数,上面坐着等待的顾客,顾客在到来这个事件时,需判断有没有空闲的椅子,理发师决定要理发或睡觉时,也要判断椅子上有没有顾客。

所以,顾客和理发师之间的关系表现为:(1)理发师和顾客之间同步关系:当理发师睡觉时顾客近来需要唤醒理发师为其理发,当有顾客时理发师为其理发,没有的时候理发师睡觉。

(2)理发师和顾客之间互斥关系:由于每次理发师只能为一个人理发,且可供等侯的椅子有限只有n把,即理发师和椅子是临界资源,所以顾客之间是互斥的关系。

(3)故引入3个信号量和一个控制变量:ⅰ控制变量waiting用来记录等候理发的顾客数,初值为0;ⅱ信号量customers用来记录等候理发的顾客数,并用作阻塞理发师进程,初值为0;ⅲ信号量barbers用来记录正在等候顾客的理发师数,并用作阻塞顾客进程,初值为1;ⅳ信号量mutex用于互斥,初值为1using System;using System.Collections.Generic;using System.Text;using System.Threading;namespace理发师问题2{internal class Program{// Fieldsprivate static Semaphore barbers = new Semaphore(1, 10);private static int chairs;private static int count = 0;private static Semaphore customers = new Semaphore(0, 10);private static int finish = 0;private static Semaphore mtx = new Semaphore(1, 10);private static int waiting = 0;// Methodspublic static void barber(){while (true){customers.WaitOne();mtx.WaitOne();waiting--;barbers.Release();mtx.Release();cuthair();finish++;}}public static void customer(){mtx.WaitOne();count++;Console.WriteLine("叮咚!第{0}个顾客来了", count);if (waiting < chairs){if (waiting > 0){Console.WriteLine("此时有{0}个人在等待理发", waiting);}else{Console.WriteLine("没有人在等待");}waiting++;Console.WriteLine("还有{0}个座位,顾客留下", (chairs - waiting) + 1);mtx.Release();customers.Release();barbers.WaitOne();gethaircut();}else{Console.WriteLine("座位已满,第{0}个顾客离开", count); mtx.Release();}}public static void cuthair(){Console.WriteLine("开始理发!这是理发师的第{0}个顾客.", finish + 1);Thread.Sleep(0x2328);Console.WriteLine("理发完成 !");}public static void gethaircut(){Thread.Sleep(0x238c);Console.WriteLine("第{0}个顾客理发完毕,离开.", finish);}private static void Main(string[] args){string str = string.Empty;Console.WriteLine("请输入椅子的总数目:");chairs = Convert.ToInt32(Console.ReadLine());Console.WriteLine("理发店共有{0}把椅子", chairs);Console.WriteLine("开门接待顾客吗?Y/N");for(string str2 = Console.ReadLine(); (str2 != "Y") && (str2 != "y"); str2 = Console.ReadLine()){Console.WriteLine("********对不起,尚未开门!********");Console.WriteLine("开门接待顾客吗?Y/N");}Console.WriteLine("********营业中,欢迎光临!********");new Thread(new ThreadStart(Program.barber)).Start();while ((str != "y") && (str != "Y")){Random random = new Random(lisecond);Thread.Sleep(random.Next(1, 0x2710));Console.WriteLine("*******************************");new Thread(new ThreadStart(Program.customer)).Start();if ((finish >= 10) && (waiting == 0)){Console.WriteLine("已经为{0}个顾客理发了,要关门下班吗?(Y/N)", finish);str = Console.ReadLine();}if ((str == "Y") || (str == "y")){Console.WriteLine("************暂停营业!**********");break;}}}}}题目: 用多线程同步方法解决睡眠理发师问题(Sleeping-Barber Problem)理发店有一位理发师,一把理发椅和n把用来等候理发的椅子。

进程同步与互斥课程设计

进程同步与互斥课程设计

进程同步与互斥课程设计一、课程目标知识目标:1. 理解进程同步与互斥的概念,掌握其基本原理;2. 学会使用同步互斥机制解决实际问题,了解其在操作系统中的应用;3. 掌握进程同步互斥的常用算法,如信号量、管程等;4. 了解进程死锁与饥饿的概念,分析其产生原因及解决方法。

技能目标:1. 能够运用同步互斥机制设计简单的并发程序;2. 能够分析并解决进程同步互斥中的问题,如死锁、饥饿等;3. 能够运用所学知识,对实际操作系统中的同步互斥问题进行优化。

情感态度价值观目标:1. 培养学生对操作系统学科的兴趣,激发其学习热情;2. 培养学生的团队协作意识,学会与他人共同分析、解决问题;3. 培养学生的创新思维,敢于尝试解决实际问题;4. 培养学生严谨的科学态度,注重理论与实践相结合。

课程性质:本课程为计算机科学与技术专业高年级学生的专业核心课程,旨在使学生掌握操作系统中的进程同步与互斥知识,具备实际应用能力。

学生特点:学生已具备一定的编程基础和操作系统基本知识,具备分析问题的能力,但可能对进程同步互斥的理解不够深入。

教学要求:结合学生特点,采用案例教学、分组讨论等方式,注重理论与实践相结合,提高学生的实际应用能力。

通过本课程的学习,使学生能够更好地理解和掌握进程同步与互斥知识,为后续课程和实际工作打下坚实基础。

二、教学内容1. 进程同步与互斥基本概念:包括进程同步的定义、互斥的概念及其重要性;2. 同步互斥机制:信号量、管程的原理与实现,以及其在并发程序中的应用;3. 死锁与饥饿问题:死锁的定义、产生原因、预防与避免策略,饥饿现象及其解决方案;4. 同步互斥算法实例分析:分析经典同步互斥算法,如生产者-消费者问题、读者-写者问题等;5. 操作系统中的应用:结合实际操作系统,分析同步互斥机制在文件系统、进程管理等方面的应用;6. 进程同步互斥编程实践:设计并发程序,运用同步互斥机制解决实际问题。

教学内容安排与进度:第1周:进程同步与互斥基本概念;第2周:同步互斥机制(信号量、管程);第3周:死锁与饥饿问题;第4周:同步互斥算法实例分析;第5周:操作系统中的应用;第6周:进程同步互斥编程实践。

操作系统实验-进程同步与互斥

操作系统实验-进程同步与互斥

操作系统实验-进程同步与互斥实验四:进程的管道通信实验题目进程的管道通信实验目的加深对进程概念的理解,明确进程和程序的区别。

学习进程创建的过程,进一步认识进程并发执行的实质。

分析进程争用资源的现象,学习解决进程互斥的方法。

学习解决进程同步的方法。

掌握Linux系统中进程间通过管道通信的具体实现实验内容使用系统调用pipe()建立一条管道,系统调用fork()分别创建两个子进程,它们分别向管道写一句话,如:Child process1 is sending a message!Child process2 is sending a message!父进程分别从管道读出来自两个子进程的信息,显示在屏幕上。

当然,仅仅通过屏幕上输出这两句话还不能说明实现了进程的管道通信,为了能够更好的证明和显示出进程的同步互斥和通信,在其中要加入必要的跟踪条件,如一定的输出语句等,来反映程序的并发执行情况实验要求这是一个设计型实验,要求自行、独立编制程序。

两个子进程要并发执行。

实现管道的互斥使用。

当一个子进程正在对管道进行写操作时,另一个欲写入管道的子进程必须等待。

使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定。

实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。

为了清楚的反应进程的同步,在子进程完成相应的操作后,调用sleep()函数睡眠一段时间(程序中定为3s)。

父进程先执行wait()函数,当有子进程执行完毕后,会得到子进程的返回结果并清理子进程。

若子进程没执行完,父进程一直执行wait()进行监听,知道有一个子进程执行完成为僵尸进程。

程序中用到的系统调用因为程序时在linux系统上进行编写的,所以其中要利用到相关的linux提供的系统调用。

所用到的系统调用包含在如下头文件中。

#include#include#include#include#include#includefork() 用于创一个子进程。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

进程之间的同步互斥与通信理发师问题操作系统课程设计操作系统课程设计目录1. 课程设计目的 (3)2. 设计要求 (3)3. 问题具体描述 (3)4. 设计分析 (3)5. 设计分工 (4)6. 数据结构说明 (4)7. 系统结构说明 (4)8. 系统调用说明 (4)9. 分工设计说明 (5)10. 算法流程图 (5)11. 分工代码 (6)12. 整体代码 (7)13. 程序运行 (10)14. 总结 (11)1.课程设计目的1.内容围绕操作系统原理中最重要的基本概念和基本原理展开2.巩固对原理知识的学习效果3.加深对基本概念的理解4.学习如何将基本原理和实际设计、应用有机结合5.锻炼本专业的基本能力2.设计要求1:进程间通信、并发(同步/互斥)、文件读写2:内存管理、Dll、Windows消息机制、IO (尚未最终定型)3.问题具体描述1.完成N个生产者和M个消费者之间的并发控制,N、M不低于5,数据发送和接收缓冲区大小不小于10个。

2.某个生产者进程生产的消息供K个消费者进程消费。

K《=M。

某些消费进程消费多个生产者生产的消息。

生产者和消费者之间的对应关系可以在程序开始有一个文件中读入,也可以动态调整。

3.每个生产进程生产M个消息后结束运行。

如果一个消费者进程没有对应的生产者进程在运行后,也结束运行。

4.设计分析课程设计的主要目的是了解并且掌握进程之间的同步互斥,和进程之间的通信问题。

结合课本上的生产者与消费者问题可以从这方面来实现一个多进程的小系统,并且解决多个进程之间的通信,并发等问题,以此来达到课程设计的目的。

理发师问题是将顾客看做生产者,将理发师作为消费者。

设置一定数量的椅子的数目来作为缓存区的大小。

顾客来到的时候坐在椅子上,将自己作为“产品”,理发师理发的时候从椅子上叫走顾客,相当于消费“产品”,从而达到了课程设计要求的前一个要求。

顾客作为生产者,每到来一个就使计数器count增加1,以便让理发师理发(相当于消费)至最后一个顾客(相当于产品)。

并且,第1个到来的顾客应负责唤醒理发师;如果不是第1个到达的顾客,则在有空椅子的情况下坐下等待,否则离开理发店(该消息可由计数器count获得)。

主要有以下一些函数来实现整个问题的实现过程:(1)用随机函数random()来产生进入理发店的顾客。

(2)定义理发师的理发函数cuthair()用来实现理发操作。

(3)定义顾客被理发的函数gethaircut()用来实现顾客被理发的操作。

(4)用顾客线程customer实现对顾客行为的控制。

(5)用理发师线程barber实现对理发师行为的控制。

(6)定义主函数main实现对两个线程的控制和执行操作。

5.设计分工成员:李宁侯绍立分工:理发师进程、信号量的设置、理发师函数:xxx顾客进程、顾客函数、主函数:xx6.数据结构说明本程序用到了数据结构中的队列,理发的顾客由随机函数产生,顾客遵从先到先理发的原则,但队列的长度限制为输入的理发店中的椅子的个数,当理发店的椅子没有空位的时候,到来的顾客主动退出加入队列。

理发师对队列中的顾客进行先到先服务的原则理发。

7. 系统结构说明(一)头文件声明#include "windows.h"#include "iostream.h"#include "math.h"(二)定义各种变量int long waiting(0);int chairs;char open_door;char close_door;int count(0);int finish(0);(三)信号量的定义HANDLE Mutex =::CreateMutex(NULL, FALSE, "Mutex");HANDLE barbers =::CreateSemaphore(NULL, 1,1, "barbers");HANDLE customers =::CreateSemaphore(NULL,0,3,"customers");8. 系统调用说明(1)CreateThread():创建线程(2)CreateMutex():找出当前系统是否已经存在指定进程的实例。

如果没有则创建一个互斥体,用来同步。

如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

CreateMutex()函数可用来创建一个有名或无名的互斥量对象(3)CreateSemaphore():CreateSemaphore() 是系统提供的API,包含在Windows.h 中,应用在同步的处理中。

作用是创建一个新的信号机,执行成功,返回信号机对象的句柄;零表示出错。

一旦不再需要,一定记住用CloseHandle关闭信号机的句柄。

它的所有句柄都关闭以后,对象自己也会删除。

一旦值大于零,信号机就会触发(发出信号)。

Semaphore是一个同步问题机制,不论是Event或Mutex,其他Process在执WaitForSingleObject时,就看当时的物件是Signal或UnSignal而决定是否等待,而Semaphore也相同,但是它要变成Signal/UnSignal的状态,却有些不同,它是提供一个计数值,它允许在这个计数值之内,任何执行到WaitForSingleObject的Thread都不会停下来,而且每执行WaitForSingleObject一次,计数值就减一,当计数值变成0时,该Semaphore才会处於UnSignal的状态,而某个Thread ReleaseSemaphore时,便会将计数值增加,以便其他的Thread或本身可得Signal的讯号,而使WaitForSingleObject停止等待。

(4)ReleaseSemaphore():ReleaseSemaphore ()函数的作用是增加信号机的计数。

如果成功,就调用信号机上的一个等待函数来减少它的计数。

(5)WaitForSingleObject():函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。

参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。

若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。

(6)ResumeThread():线程恢复函数,使用该函数能激活线程的运行,使CPU分配资源让线程恢复运行。

(7)ReleaseMutex():释放由线程拥有的一个互斥体(8)Sleep():睡眠等待9. 分工设计说明需要用到的信号量:HANDLE Mutex =::CreateMutex(NULL, FALSE, "Mutex");实现顾客与理发师对公用缓存区的互斥操作HANDLE barbers=::CreateSemaphore(NULL, 1,1, "barbers"); HANDLE customers=::CreateSemaphore(NULL,0,3,"customers"); ::WaitForSingleObject(customers,INFINITE); 等待顾客进程的V(customer)操作::WaitForSingleObject(Mutex,INFINITE); 申请操作顾客与理发师公用的缓存区::ReleaseSemaphore(barbers,1,NULL); 释放信号量barbers::ReleaseMutex(Mutex); 释放信号量Mutex,允许顾客操作缓存区10.算法流程图11.分工代码#include "windows.h"#include "iostream.h"#include "math.h"int long waiting(0); //等待理发的顾客人数int chairs; //店中椅子的总数目char open_door; //开门char close_door; //关门int count(0); //顾客的序号int finish(0); //已经理完发的顾客人数DWORD a;HANDLE Mutex =::CreateMutex(NULL, FALSE, "Mutex"); //用来实现进程的互斥HANDLE barbers =::CreateSemaphore(NULL, 1,1, "barbers"); //定义信号量来进行线程间的同步HANDLE customers =::CreateSemaphore(NULL,0,3,"customers"); //定义信号量来进行线程间的同步int random()//定义随机函数来产生顾客,并使两个顾客间的时间少于15秒{return (rand()*15000)/RAND_MAX;}void cuthair()//理发师的理发函数,用时15秒{::Sleep (15000);cout<<"理发结束!"<<endl;}DWORD WINAPI barber(LPVOID pParm1) //理发师线程{while(true){::WaitForSingleObject(customers,INFINITE) ;//p(customers),等待顾客::WaitForSingleObject(Mutex,INFINITE); //等待互斥量waiting--;//等待的人数减1::ReleaseSemaphore(barbers,1,NULL);//释放信号量::ResumeThread(barbers);//唤醒顾客进程::ReleaseMutex(Mutex);//v(mutex);cuthair();finish++;}return 0;}12.整体代码#include "windows.h"#include "iostream.h"#include "math.h"int long waiting(0); //等待理发的顾客人数int chairs; //店中椅子的总数目char open_door; //开门char close_door; //关门int count(0); //顾客的序号int finish(0); //已经理完发的顾客人数DWORD a;HANDLE Mutex =::CreateMutex(NULL, FALSE, "Mutex"); //用来实现进程的互斥HANDLE barbers =::CreateSemaphore(NULL, 1,1, "barbers"); //定义信号量来进行线程间的同步HANDLE customers =::CreateSemaphore(NULL,0,3,"customers"); //定义信号量来进行线程间的同步int random()//定义随机函数来产生顾客,并使两个顾客间的时间少于15秒{return (rand()*15000)/RAND_MAX;}void cuthair()//理发师的理发函数,用时15秒{::Sleep (15000);cout<<"理发结束!"<<endl;}void gethaircut()// 顾客被理发的函数{::Sleep (15001); //顾客被理发的函数,为了和理发师之间有所区别,比理发师理发时间长1毫秒cout<<"第"<<finish<<"个顾客理发完毕,离开"<<endl;}DWORD WINAPI customer(LPVOID pParm2) // 顾客线程{::WaitForSingleObject(Mutex ,INFINITE); //P(mutex)来进行互斥操作count++;//来的是第几个顾客cout<<"顾客敲门!第"<<count<<" 个顾客到来"<<endl;if (waiting<chairs)//如果有空椅子{if (waiting!=0){cout<<"现在有"<<waiting <<" 个人在等待理发"<<endl;}elsecout<<"无人在等待理发"<<endl; //输出有多少人在等待waiting++;cout<<"剩余"<<chairs-waiting+1<<"个座位"<<endl;cout<<"有空位,顾客已坐下"<<endl;::ReleaseSemaphore(customers,1,NULL); //V(customer)::ResumeThread(customers); //唤醒理发师进程::ReleaseMutex(Mutex); //释放互斥量,以便其他线程使用::WaitForSingleObject(barbers,INFINITE);//等待理发gethaircut();}else{cout<<"没有空椅子,第"<<count<<"个顾客离开理发店"<<endl; //没有椅子,顾客直接离开::ReleaseMutex(Mutex);}return 0;}DWORD WINAPI barber(LPVOID pParm1) //理发师线程{while(true){::WaitForSingleObject(customers,INFINITE) ;//p(customers),等待顾客::WaitForSingleObject(Mutex,INFINITE); //等待互斥量waiting--;//等待的人数减1::ReleaseSemaphore(barbers,1,NULL);//释放信号量::ResumeThread(barbers);//唤醒顾客进程::ReleaseMutex(Mutex);//v(mutex);cuthair();finish++;}return 0;}int main(int argc, char* argv[])//实现线程的操作{cout<<"输入理发店中的椅子个数:"; cin>>chairs;cout<<"店中有"<<chairs<<"把椅子"<<endl; //设置椅子数目cout<<"是否开始接待顾客?Y/N"<<endl;//是否开门营业cin>>open_door;while (open_door!='y'){cout<<endl<<"尚未营业!"<<endl;cout<<"是否开始接待顾客?Y/N"<<endl;cin>>open_door;}HANDLE hThread1;HANDLE hThread2;hThread2=::CreateThread(NULL,0,barber,NULL,0,NULL); //产生一个理发师进程while(close_door!='y'){::Sleep(random());//函数实现顾客随机到来hThread1=::CreateThread(NULL,0,customer, NULL,a,NULL);cout<<endl<<"正在营业,请进!"<<endl;if (finish>=8 && waiting==0)//如果完成数超过8并且没有人等待{cout<<"已经为"<<finish<<"个顾客理发了,是否停止营业?"<<endl; //提示是否关门cin>>close_door;return close_door;}}if (close_door=='y'){cout<<"暂停营业!欢迎下次光临!"<<endl;return 0;}return 0;}13.程序运行开始输入椅子数目选择是否接待顾客接待顾客理发完毕14.总结通过这个课程设计,对于课本上的关于进程之间的同步、互斥有了更深层的认识,而且有了具体上直观上的理解。

相关文档
最新文档