模拟PV操作同步机构-且用PV操作解决生产者——消费者问题。
操作系统实验——PV操作实现生产者消费者模型

/** * 单个生产者类 * @author Vfdxvffd * @count 生产的物品数量标号 */ class Producer implements Runnable{ int count = 0; //数量 @Override public void run() { while(count < 20) { //最多生产20件商品
Global.empty.Wait(); /*要生产物品了,给剩余空 闲缓冲区数量--,如果减完后变为负数,则说明当前没 有空闲缓冲区,则加入等待队列*/ //临界区,生产商品 int index = count % 2; Global.buffer[index] = count; System.out.println("生产者在缓冲区"+index+"中生产了物品"+count); count++;
假如生产者号生产了0号商品,但此时他还没做Global.pCount++这一步操作,CPU将执行权切换到生产者2号,这时Global.pCount的值还是 刚刚的0,没有加1,所以又会生产出一个0号商品,那消费者也同理,消费完还没加1,就被切换了执行权。
那就有个问题,如果我们将Global.pCount++这一步提前能不能解决问题呢,当然也是不行的,因为可能++完还没输出就被切换执行权,那下次 执行权回来时候就会继续执行输出操作,但此时的Global.pCount的值已经不知道加了多少了。
/*remove a process P from the waiting queue*/ wakeup(P); } }
信号量的应用
【精品】操作系统习题1

【关键字】精品第一章1. 操作系统的主要作用是()A 管理设备B 提供操作命令C 管理文件D 为用户提供使用计算机的接口,管理计算机的资源2. 对外部输入的信息能在规定时限内处理完毕并作出迅速反应的操作系统称为()A 分时操作系统B 批处理操作系统C 实时操作系统D 多处理机操作系统3. 操作系统的基本特征是、、、。
4. 什么是操作系统?第二章1 . 苹果桔子问题桌上有一只盘子,每次只能存放一个水果。
一家四口人各行其职,爸爸专向盘子中放苹果(apple),妈妈专向盘子中放桔子(orange),儿子专等吃盘子中的桔子,女儿专等吃盘子里的苹果。
请用PV操作来实现四人之间的同步算法。
2. 和尚取水问题寺庙里有老小和尚若干和一水缸,小和尚打水,老和尚饮水。
水缸容积为10桶水,水取自同一水井,每次只容一个桶打水,桶的总数为3个,每次往水缸倒水和从水缸取水仅为一桶。
3.有一座东西方向的独木桥,用P,V操作实现:(1)每次只允许一个人过桥;(2)当独木桥上有行人时,同方向的行人可以连续过桥,相反方向的人必须等待。
(3)当某一方向无人过桥时,另一方向的行人可以过桥。
4.上图描述的生产者-消费者问题中,如果其缓冲区部分为n个长度相等的有界缓冲区组成,且每次传输数据长度等于有界缓冲区长度以及生产者和消费者可对缓冲区同时操作。
试重新描述生产过程和消费过程。
5. 若信号量的初值为2,当前值为-3,则表示有()等待进程。
A 1个B 2个C 3个D 5个6. 在操作系统中,()是竞争和分配计算机系统资源的基本单位。
A 程序B 进程C 作业D 用户7. 下面哪一个不会引起进程创建()A 用户登录B 作业调度C 设备分配D 应用请求8. 进程和程序的本质区别是()A 内存和外存B 动态和静态特征C共享和独占使用计算机资源D顺序和非顺序执行机器指令9. 在多进程的系统中,为了保证公共变量的完整性,各进程应互斥进入临界区。
所谓临界区是()A 一个缓冲区B 一个数据区C 一种同步机构D 一段程序10. 在一辆公共汽车上,司机和售票员各行其职,司机负责开车和到站停车,售票员负责售票和开、关门,当售票员关好车门后,驾驶员才能继续开车行驶。
P.V原语操作

x: =B[out];
out: =(out+1) mod10;
v (s1);
consume (x);
goto L2
end;
coend.
其中的semaphore和products是预先定义的两个类型,在模拟实现中semaphore用integer代替,products可用integer或char等代替。
[提示]:
(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:
P操作原语P (s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V (s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:
end {v}
其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2) 生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。消费者每次从缓冲器内取出一件产品去消费。禁止生产者将产品放入已满的缓冲器内,禁止消费者从空缓冲器内以产品。假定缓冲器内可同时存放10件产品。那么,用PV操作来实现生产者和消费者之间的同步,生产者和消费者两个进程的程序如下:
default: printf("结束操作"); m=0;
} emptyຫໍສະໝຸດ +; } else
{
printf("缓存池已空无法执行消费操作\n");
PV操作(生产者-消费者问题)

PV操作(生产者-消费者问题) /* 用信号量解决生产者-消费者问题*/#include <STDIO.H>#define N 10typedef int semaphore; /* 信号量是一种特殊的整型变量*/semaphore mutex=1; /* 互斥访问*/semaphore empty=N; /* 记录缓冲区中空的槽数*/semaphore full=0; /* 记录缓冲区中满的槽数*/semaphore buf[N]; /* 有N个槽数的缓冲区buf[N],并实现循环缓冲队列*/ 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 item\n");*/*item_ptr='m'; /* 'm' is "man满" */}void enter_item(int x){front=(front+1)%N;buf[front]=x;printf("enter_item %c to buf[%d]\n", buf[front], front);}void remove_item(int *yy){rear=(rear+1)%N;printf("remove_item %c from buf[%d]", buf[rear], rear);*yy=buf[rear];buf[rear]='k'; /* 'k' is "kong空" */printf(" so the buf[%d] changed to empty--%c\n", rear, buf[rear]);}void consume_item(int y){printf("cosume the item :the screem print %c\n", 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;}。
实验4 进程同步-生产者消费者实验

实验四生产者消费者实验:用信号量实现PV操作实验目的1、熟悉PV操作的实现原理。
2、了解进程间通信机制。
熟悉信号量机制。
使用信号量机制模拟实现PV操作,从而控制多个进程对共享资源的使用。
实验内容1、使用信号量机制来模拟实现PV操作。
2、编写一个简单的程序,使用该PV模拟操作控制多进程对共享资源的使用。
实验基础一、信号量基础1、进程间通信机制进程间通信机制包括共享内存(shared memory)、信号量(semaphores)和消息队列(Message Queue)等一系列进程通信方式。
System V IPC的进程间通信机制一个显著特点是:在内核中它的具体实例是以对象的形式出现的——被称之为IPC对象。
每个IPC对象在系统内核中都有一个惟一的标识符。
通过标识符内核可以正确地引用指定的IPC对象。
要注意的是,标识符的惟一性只在每一类的IPC对象内成立。
例如,一个消息队列和一个信号量的标识符可能相同,但是绝对不允许两个消息队列使用相同的标识符。
IPC对象在程序中通过关键字(key)来访问内核中的标识符。
与IPC对象标识符相同,关键字也是惟一的。
而且,如果要访问同一个IPC对象,客户和服务器就必须使用同一个关键字。
因此,建立IPC对象时要解决的首要的一个问题,就是如何构造新的关键字使之不与已有的关键字发生冲突,并能保证客户和服务器使用相同的关键字。
2、信号量信号量是一个计数器,用来控制多个进程对共享资源的使用。
进程为了获得共享资源,需要执行下列操作:(1) 测试控制该资源的信号量。
(2) 若此信号量的值为正,则进程可以使用该资源。
进程将信号量值减1,表示它使用了一个资源单位。
(3) 若此信号量的值为0,则进程进入睡眠状态,直至信号量值大于0。
若进程被唤醒后,它返回至(第(1)步)。
当进程不再使用由一个信息量控制的共享资源时,该信号量值增1。
如果有进程正在睡眠等待此信号量,则唤醒它们。
为了正确地实现信息量,信号量值的测试及减1操作应当是原子操作。
计算机操作系统PV操作例题

问题1 一个司机与售票员的例子在公共汽车上,为保证乘客的安全,司机和售票员应协调工作:停车后才能开门,关车门后才能行车。
用PV操作来实现他们之间的协调。
S1:是否允许司机启动汽车的变量S2:是否允许售票员开门的变量driver()//司机进程{while (1)//不停地循环{P(S1);//请求启动汽车启动汽车;正常行车;到站停车;V(S2); //释放开门变量,相当于通知售票员可以开门}}busman()//售票员进程{while(1){关车门;V(S1);//释放开车变量,相当于通知司机可以开车售票P(S2);//请求开门开车门;上下乘客;}}注意:busman() driver() 两个不停循环的函数问题2 图书馆有100个座位,每位进入图书馆的读者要在登记表上登记,退出时要在登记表上注销。
要几个程序?有多少个进程?(答:一个程序;为每个读者设一个进程)(1)当图书馆中没有座位时,后到的读者在图书馆为等待(阻塞)(2)当图书馆中没有座位时,后到的读者不等待,立即回家。
解(1 )设信号量:S=100; MUTEX=1P(S)P(MUTEX)登记V(MUTEX)阅读P(MUTEX)注销V(MUTEX)V(S)解(2)设整型变量COUNT=100;信号量:MUTEX=1;P(MUTEX);IF (COUNT==0){ V(MUTEX);RETURN;}COUNT=COUNT-1;登记V(MUTEX);阅读P(MUTEX);COUNT=COUNT+1;V(MUTEX);RETURN;问题3 有一座东西方向的独木桥;用P,V操作实现:(1)每次只允许一个人过桥;(2)当独木桥上有行人时,同方向的行人可以同时过桥,相反方向的人必须等待。
(3)当独木桥上有自东向西的行人时,同方向的行人可以同时过桥,从西向东的方向,只允许一个人单独过桥。
(此问题和读者与写者问题相同,东向西的为读者,西向东的为写者)。
(1)解设信号量MUTEX=1P (MUTEX)过桥V (MUTEX)(2)解设信号量:MUTEX=1 (东西方互斥)MD=1 (东向西使用计数变量互斥)MX=1 (西向东使用计数变量互斥)设整型变量:CD=0 (东向西的已上桥人数)CX=0 (西向东的已上桥人数)从东向西:P (MD)IF (CD=0){P (MUTEX) }CD=CD+1V (MD)过桥P (MD)CD=CD-1IF (CD=0){V (MUTEX) }V (MD)从西向东:P (MX)IF (CX=0){P (MUTEX) }CX=CX+1V (MX)过桥P (MX)CX=CX-1IF (CX=0){V (MUTEX) }V (MX)(3) 解:从东向西的,和(2)相同;从西向东的和(1)相同。
第4章(401)

进程 A …
P(S); CSA; V(S); …
进程 B …
P(S); CSB; V(S) …
第 4 章 进程同步与通信
对于两个并发进程,互斥信号量的值仅取1、0、-1三个 值。
若S=1,表示没有进程进入临界区; 若S=0,表示有一个进程进入临界区; 若S= -1,表示一个进程进入临界区,另一个进程等待进 入。 下面请大家思考这样一个问题,如果N个并发进程共用 一个公共变量Q,用信号量和PV操作实现这N个进程的互斥, 信号量的取值范围如何呢?
第 4 章 进程同步与通信
若系统中存在一组进程的执行在时间上是重叠的,就称 该组进程具有并发性,这组进程就被称为“并发进程”。
并发进程相互之间可能是无关的,也可能是有交往的。 如果一个进程的执行不影响其他进程的执行,且与其他进程 的进展情况无关,即它们是各自独立的,则称这些并发进程 相互之间是无关的。如果一个进程的执行可能影响其他进程 的执行结果,则称这些并发进程相互之间是有交往的。对于 有交往的并发进程来说,可能有若干并发进程同时使用共享 资源,即一个进程一次使用未结束,另一进程就开始使用, 形成交替使用共享资源。如果对这种情况不加控制,在共享 资源时就会出错。
while(1) { observe a lorry;
count=count+1; } }
第 4 章 进程同步与通信
Process Reporter { while(1) { printf("%d",count); count=0; } }
coend }
第 4 章 进程同步与通信
在cobegin 和coend之间的进程为可并发执行的进程。观 察者进程和报告者进程并发执行时可能有如下两种情况:
操作系统PV操作习题

操作系统PV操作习题操作系统PV操作习题-----------------------------------------------------1、引言在操作系统中,PV操作(也称作P操作和V操作)是用于进程同步的一种常见机制。
P操作用于获取或申请资源,V操作用于释放资源。
本文将为您提供一些关于PV操作的习题,以帮助您巩固相关的概念和原理。
2、PV操作基本概念2.1 P操作描述P操作的基本概念和含义,以及在实际应用中的具体场景。
2.2 V操作解释V操作的基本概念和含义,并举例说明其在实际问题中的应用。
3、PV操作习题集3.1 习题一、生产者-消费者问题描述一个典型的生产者-消费者问题,并通过使用P操作和V操作对其进行解决。
3.2 习题二、读者-写者问题解释一个典型的读者-写者问题,并使用PV操作来实现对该问题的解决。
3.3 习题三、哲学家就餐问题描述哲学家就餐问题的场景,并说明如何采用PV操作来解决这一问题。
4、常见PV操作错误4.1 死锁解释什么是死锁以及为什么会发生死锁现象,同时提供一些避免死锁的方法。
4.2 饥饿描述什么是饥饿,以及一些可能导致饥饿的常见原因,并提供解决饥饿问题的一些策略。
5、附录本文档附带以下附件:- 习题的解答和详细说明- 相关的代码示例6、法律名词及注释在本文档中,涉及的法律名词及其注释如下:- PV操作:即P操作和V操作,用于进程同步的一种机制。
- 生产者-消费者问题:一种经典的并发控制问题,涉及到生产者和消费者之间的资源竞争。
- 读者-写者问题:一种并发控制问题,涉及到多个读者和写者对共享资源的访问。
- 哲学家就餐问题:一种经典的并发控制问题,涉及到多个哲学家通过共享的餐具进行就餐。
操作系统实验报告三大问题之生产者与消费者问题

计算机操作系统实验报告题目三大经典问题之生产者与消费者问题一、课程设计的性质与任务1、加深对并发协作进程同步与互斥概念的理解。
通过编写程序实现进程同步和互斥,使学生掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥等有关的内容。
2、掌握进程和线程的概念,进程(线程)的控制原语或系统调用的使用。
3、了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。
学习使用Windows2000/XP中基本的同步对象,掌握相应的API函数。
4、培养学生能够独立进行知识综合,独立开发较大程序的能力。
5、培养提高学生软件开发能力和软件的调试技术。
6、培养学生开发大型程序的方法和相互合作的精神。
7、培养学生的创新意识。
8、培养学生的算法设计和算法分析能力。
9、培养学生对问题进行文字论述和文字表达的能力。
二、课程设计的内容及其要求在Windows?XP、Windows?2000等操作系统下,使用的VC、VB、Java或C等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。
要求:(1)经调试后程序能够正常运行。
(2)采用多进程或多线程方式运行,体现了进程(线程)同步互斥的关系。
(3)程序界面美观。
三、实验原理本实验要求利用PV操作实现解决生产者——消费者问题中的同步问题。
此问题描述的是一群生产者进程在生产产品并将这些产品提供给消费者进程去消费,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将它所生产的产品放入一个缓冲区,消费者进程可从缓冲区中取走产品去消费,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满且尚未取出的缓冲区中投放产品,并且生产者消费者互斥使用缓冲区。
四、实验原理图五、算法实现(1)有一个生产者线程ProduceThread,有1个消费者进程CustomerThread;缓冲区为shareList。
用P,V操作实现进程的同步与互斥

用P,V操作实现进程的同步与互斥摘要:进程的同步与互斥是操作系统中的重要问题。
通过P,V操作可以实现进程的同步与互斥。
本论文从P,V操作的原理入手,详细介绍了P,V操作在进程中的应用,以及它们对进程同步和互斥的作用。
通过本文的阐述,读者可以深入理解操作系统中P,V操作的实现原理及其在进程中的应用。
关键词:P,V操作;进程同步;进程互斥正文:1.引言进程的同步与互斥是操作系统中的重要问题。
同步是指在多进程环境下,控制进程之间相互合作的过程,互斥则是指在同一时间,只允许一个进程访问共享资源的过程。
为了实现进程的同步与互斥,操作系统中通常使用P,V操作。
2.P,V操作原理P,V操作是一种原子操作,它们可以保证在多进程环境下的资源访问的同步和互斥。
P操作用于请求共享资源,如果资源已被其他进程占用,那么当前进程就会被阻塞,等待资源释放;V操作用于释放共享资源,如果有其他进程正在等待该资源,那么就会唤醒其中一个进程继续执行。
3.P,V操作在进程中的应用在进程中,P,V操作主要用于实现进程之间的同步与互斥。
在同步方面,可以通过P操作等待其他进程执行完毕才继续执行;在互斥方面,可以通过P操作占用共享资源,在使用完毕后通过V操作释放资源。
4.P,V操作对进程同步和互斥的作用P,V操作对进程同步和互斥的作用十分重要。
在同步方面,P操作可以协调多个进程的执行顺序,使得它们按照一定的规则执行;在互斥方面,P操作可以保证同一时间只有一个进程占用共享资源,有效避免了资源冲突问题。
5.总结通过P,V操作可以实现进程的同步与互斥。
本文详细介绍了P,V操作的原理及其在进程中的应用,以及它们对进程同步和互斥的作用。
实践证明,P,V操作是一种有效的实现进程同步与互斥的方法。
6. P,V操作的局限性虽然P,V操作能够解决进程同步与互斥问题,但是它们也存在一些局限性。
首先,P,V操作采用了忙等待的方式,需要不断地检测是否可以进行操作,这会占用CPU资源。
操作系统的课程设计

石家庄经济学院信息工程学院操作系统课程设计(计算机科学与技术专业用)班级5040109031学号403010903104姓名指导教师2006 年1 月13 日免责声明:文档在线网(文档中国)中所有的文档资料均由文档在线网会员提供。
文档在线网会对会员提供的文档资料进行筛选和编辑,但是并不声明或保证其内容的合法性、正确性或可靠性。
该文档资料的版课程设计任务书班级姓学号课程设计起止日期2006 年1 月2 日至2006 年1 月13 日实习地点260机房152机房课程设计题目主存储器的分配与回收课程设计内容与要求内容:模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
要求:首先进行软件设计,编写程序,并调试通过。
指导教师200 年月日一、课程设计目的了解在不同的存储管理方式下应怎样实现主存空间的分配和回收。
二、软硬件环境1. 硬件配置内存512;CPU inter pentinum®4 2.80G赫兹。
2.软件配置windows.xp、visual C++6.0。
三、系统设计及开发过程1. 系统具体设计过程(1).模拟PV操作同步机构,PV操作同步机构,有P操作原语和V操作原语组成,他们定义如下:P操作原语P(S):将信号量S减去1,若结果小于0,则执行原语的进程被置成等待信号量S的状态。
V 操作原语V(S):将信号量S加1,若结果不大于0,则释放一个等待信号量S的进程。
(2).假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
消费者每次从缓冲内取出一件产品去消费。
禁止生产者将产品放入以满的缓冲器内,禁止消费者从空缓冲器内取走产品。
(3).模拟处理器调度程序:每当执行一条模拟的指令后,保护当前进程的现场,让它成为非运行态,由处理器调度程序按随机数再选择一个就绪进程占用处理器运行。
PV操作解决生产者——消费者问题

public synchronized void consume() { // 实现消费的函数 // 唤醒生产者 this.notifyAll(); // 判断队列是否为空 while (queue.size() == 0) {
-5-
output(Thread.currentThread().getName() + " 消费队列空!等 待中…………"+"\n",
// 接口 public interface putmsg {
public void output(String msg, JTextArea textaera, JProgressBar jbr);
public void buffer(JTextField number); }
public Test2() { // 设置窗口大小 setSize(600, 600); // 设置窗口的位置,距离左上角(100,100) setLocation(100, 100); // 设置默认关闭,右上角的的叉关闭 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 调用函数 layoutPanel2() textbox = new JTextField("10", 2); layoutPanel2(); // 设置布局方式为边界布局,就是上下左右中也可以说东南西北中 setLayout(new BorderLayout());
-2-
产者消费者进程。随机数0执行生产者线程,随机数1执行生产者线程。至于PV 算法的实现是利用buffer_empty和buffer_full来进行控制,buffer_empty的值 可以看做资源量,只有空的数值大于0才可以进行生产,buffer_full的数值与 buffer_empty的值有对应的关系,利用buffer_full来控制消费的进行。最后, 在缓冲区操作临界资源PC_Buffer来说利用 EnterCriticalSection(&PC_Buffer );//等待共享资源 LeaveCriticalSection(&PC_Buffer );//释放共享资源来进行缓冲区操作的控 制。总之当程序读入测试文件中的数据时,便根据读入的字符时C还是P创造相应 的进程,在分配EMPTY或者FULL资源,然后等待共享资源PC_Buffer,得到后便进 行操作。最后读入所有的数据,完成所有进程的操作。
PV操作解决生产者——消费者问题介绍

(3) 详细设计 1、做出如下定义
public class Test2 extends JFrame { // 面板 1
-3-
private JPanel panel1 = new JPanel(); // 面板 2 private JPanel panel2 = new JPanel(); private JPanel panel3 = new JPanel(); // 线程 1 private static Thread threadWQ1; // 线程 2 private static Thread threadRQ1; // 文本域,可编辑多行文字的 public static JTextArea textarea;// 可以编辑多行 // 文本框,只能编辑一行 public static JTextField textbox;// 只可以编辑一行 // 滚动条 public static JScrollPane scrollpane;// 滚动条 // 进度条 public JProgressBar progressbar = new JProgressBar();// 进度条 // 队列 Queue Q = new Queue(); // 实例化生产者 Producer wQ1 = new Producer(Q); // 实例化消费者 Consumer rQ1 = new Consumer(Q); // 接口 public interface putmsg { public void output(String msg, JTextArea textaera, JProgressBar jbr); public void buffer(JTextField number); } public Test2() { // 设置窗口大小 setSize(600, 600); // 设置窗口的位置,距离左上角(100,100) setLocation(100, 100); // 设置默认关闭,右上角的的叉关闭 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 调用函数 layoutPanel2() textbox = new JTextField("10", 2); layoutPanel2(); // 设置布局方式为边界布局,就是上下左右中也可以说东南西北中 setLayout(new BorderLayout());
PV操作及进程同步的实现2哲学家就餐问题

课程设计课程设计名称:专业班级:学生姓名:学号:指导教师:课程设计时间: 2010/12/23计算机科学专业课程设计任务书说明:本表由指导教师填写,由教研室主任审核后下达给选题学生,装订在设计(论文)首页1 需求分析哲学家就餐问题是一种典型的同步问题,它是由Dijstra提出并解决的。
该问题描述如下:有五个哲学家,他们的生活方式是交替的进行思考和进餐。
哲学家们公用一张圆桌,设5个哲学家分别为A,B,C,D,E,桌子上放着5把筷子,编号分别编号为0,1,2,3,4,桌子中央有一盘饭菜。
5个哲学家都很有礼貌,都要等同时拿到身旁的两只筷子才进餐,不然就只是等着继续思考,而且吃了一口之后又马上放下拿起的两根筷子,继续思考。
由于筷子数目有限,不能让5个哲学家同事进餐,而且甚至只能让其中的少数哲学家进餐,其他的哲学家只能轮流享用。
为每个哲学家各编一段程序描述他们的行为,解决哲学家就餐问题。
2 概要设计源程序中各个函数的作用说明:int Readcount[n];int chopstick[n];//筷子状态标志void Getchopstick(int nextw)//拿起筷子函数。
nextw为哲学家标号void Dropchopstick(int nextr)//放下筷子函数int select();int main()//主函数操作实验结构图:3 运行环境硬件环境:基于Xp的PC软件环境:Windows XP4 开发工具和编程语言开发工具:Visual C++ 6.0编程语言:Visual C++5 详细设计#include<stdio.h>#define n 5int in=0;int out=0;int Readcount[n];int chopstick[n];//筷子状态标志void Getchopstick(int nextw)//拿起筷子函数。
nextw为哲学家标号{printf("第%d名哲学家肚子饿了,申请左边的筷子。
经典PV操作问题详解(最全面的PV资料)[精品]
![经典PV操作问题详解(最全面的PV资料)[精品]](https://img.taocdn.com/s3/m/5831c61dba68a98271fe910ef12d2af90242a8b4.png)
经典P、V操作问题详解*****************一、基本概念1. 信号量struct semaphore{int value; // 仅且必须附初值一次,初值非负PCBtype* wait_queue; // 在此信号量上阻塞的进程队列} S; // 信号量实例为S2. P、V操作P(S){S := S-1;if (S<0)调用进程自己阻塞自己,等待在S的等待队列末尾;}V(S){S := S+1;if (S≤0)从S等待队列头释放一进程就绪在就绪队列尾;调用进程继续执行;}3. 使用方法(i). P、V操作成队出现,处理互斥时出现在同一进程中;处理同步时出现在不同进程中。
(ii). 同步P先于互斥P调用,V的顺序无关。
4. 另类P、V操作导致的问题(或信号量的栈实现方法或漏斗法)[习题P174-23]某系统如此定义P、V操作:P(S): S = S-1; 若S<0,本进程进入S信号量等待队列的末尾;否则,继续执行。
V(S): S=S+1; 若S≤0,释放等待队列中末尾的进程,否则继续运行。
(1)上面定义的P、V操作是否合理?有什么问题?(2)现有四个进程P1、P2、P3、P4竞争使用某一个互斥资源(每个进程可能反复使用多次),试用上面定义的P、V操作正确解决P1、P2、P3、P4对该互斥资源的使用问题。
答:(1)不合理:先进后出;可能“无限等待”,即等待队列头的进程得不到释放。
(2)思路:令每个信号量上的等待队列中始终只有一个进程。
解决方案如下:(n个进程)n个进程至多有n-1个等待。
设置n-1个信号量,每个进程阻塞在不同的信号量上,使每个等待队列至多有一个进程等待。
用循环模拟队列。
Semaphore S[n-1]; // S[i]的初值为i+1Procedure_i(){int j;DO_PRE_JOB();for(j=n-2; j>=0; j--)P(S[j]);DO_JOB_IN_CRITICAL_SECTION();for(j=0;j<=n-2;j++)V(S[j]);……}二、经典进程同步问题总述:进程同步问题主要分为以下几类:一(生产者-消费者问题);二(读者写者问题);三(哲学家就餐问题);四(爱睡觉的理发师问题);五(音乐爱好者问题);六(船闸问题);七(红黑客问题)等。
《操作系统课程》实验(实训)指导大纲

《操作系统课程》实验(实训)指导大纲课程编号:G611SG0004课程性质:学科基础课适用专业:计算机科学与技术网络工程数字媒体实验学时:16实验教材:自编符合《认证标准》:具有运用工程基础知识和本专业基本理论知识解决问题的能力,具有系统的工程实践学习经历;完成本课程实验(实训)总软件最少行数: 2000实验成绩评价方法:学生每完成一个实验项目,要求独立认真的填写实验报告。
实验指导教师将根据学生完成实验的态度和表现,结合填写的实验报告评定实验成绩,成绩的评定按百分制评分。
老师根据平时实验的分数之和取平均分,得出综合成绩。
实验(实训)内容:实验一操作系统安装及熟练使用(一)实验目的熟悉Windows//Linux操作系统的安装过程与安装方法,并掌握该操作系统所提供的用户接口环境,并为后续实验做好编程环境准备。
(二)实验项目内容1、熟悉Windows//Linux操作系统的安装过程与安装方法,并掌握该操作系统所提供的用户接口环境,通过系统提供的用户管理程序、查看系统中的用户情况、进程、线程、内存使用情况等,学会使用它进行监视进程的状况、系统资源的使用情况及用户情况。
并为后续实验做好编程环境准备。
2、用C语言编写一小段程序,使其可以通过某个系统调用来获得OS提供的某种服务。
(三)主要仪器设备一台PC机(四)实验室名称计算机中心实验室(五)实验报告撰写(撰写的格式采用教务处所提供的样本见附件)......实验二编程模拟进程间的同步和互斥(一)实验目的通过实验加强对进程同步和互斥的理解,并掌握进程(线程)的创建和调用方法。
学会使用信号量解决资源共享问题。
学生可以自己选择在Windows或Linux系统下编写。
代码不得少于200行。
(二)实验项目内容1.以下为Linux系统下参考程序,请编译、运行并观察程序的输出,并分析实验结果,写出实验报告。
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<time.h>#include<sys/types.h>#include<sys/wait.h>#include<linux/sem.h>#define NUM_PROCS 5#define SEM_ID 250#define FILE_NAME "/tmp/sem_aaa"#define DELAY 4000000void update_file(int sem_set_id, char *file_path, int number){struct sembuf sem_op;FILE *file;//等待信号量的数值变为非负数,此处设为负值,相当于对信号量进行P操作sem_op.sem_num=0;sem_op.sem_op=-1;sem_op.sem_flg=0;semop(sem_set_id,&sem_op,1);//写文件,写入的数值是当前进程的进程号file=fopen(file_path,"w");if(file){//临界区fprintf(file,"%d\n",number);printf("%d\n",number);fclose(file);}//发送信号,把信号量的数值加1,此处相当于对信号量进行V操作sem_op.sem_num=0;sem_op.sem_op=1;sem_op.sem_flg=0;semop(sem_set_id,&sem_op,1);}//子进程写文件void do_child_loop(int sem_set_id,char *file_name){ pid_t pid=getpid();int i,j;for(i=0;i<3;i++){update_file(sem_set_id,file_name,pid);for(j=0;j<4000000;j++);}}int main(int argc,char **argv){int sem_set_id; //信号量集的IDunion semun sem_val; //信号量的数值,用于semctl()int child_pid;int i;int rc;// 建立信号量集,ID是250,其中只有一个信号量sem_set_id=semget(SEM_ID,1,IPC_CREAT|0600);if(sem_set_id==-1){perror("main: semget");exit(1);}//把第一个信号量的数值设置为1sem_val.val=1;rc=semctl(sem_set_id,0,SETVAL,sem_val);if(rc==-1){perror("main:semctl");exit(1);}//建立一些子进程,使它们可以同时以竞争的方式访问信号量for(i=0;i<NUM_PROCS;i++){child_pid=fork();switch(child_pid){case -1:perror("fork");case 0: //子进程do_child_loop(sem_set_id,FILE_NAME);exit(0);default: //父进程接着运行break;}}//等待子进程结束for(i=0;i<NUM_PROCS;i++){int child_status;wait(&child_status);}printf("main:we're done\n");fflush(stdout);return 0;}2.写一程序模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
PV操作解决生产者

合肥学院计算机科学与技术系实验报告2012 ~2013 学年第 1 学期2012 年12 月课程名称 计算机操作系统 课程设计名称 PV 操作解决生产者——消费者问题 专 业 班 级10级网络工程1班学生姓名 汪青松 学 生 学 号 1004031010 指 导 教 师王晓峰一、实验目的1、了解进程PV操作的过程2、了解生产者和消费者的工作过程3、理解进程同步机构的作用和意义二、实验内容模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
三、实验步骤(1)任务分析假定有一个生产者和消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
消费者每次从缓冲器内取出一件产品去消费。
禁止生产者将产品放入已满的缓冲器内,禁止消费者从空缓冲器内取产品。
假定缓冲器内可同时存放10件产品。
其中需要我们模拟的部分主要为:PCB进程控制块和模拟处理器工作部分。
(2)简要设计程序的大致过程可以设计为,先对模拟程序中的各个变量进行初始化,包括信号量s1、s2等,然后再转入处理调度程序,在进入处理调度程序时,程序并发执行,每当当前进程执行完毕后,记录下当前状态,并标记为等待状态。
然后再由处理器调度程序按随机数再选择一个就绪进程占用处理器运行。
当选取进程后再按照处理器模拟执行程序,通过一个指令计数器来控制执行的指令。
(3) 详细设计程序的大致过程可以设计为,先对模拟程序中的各个变量进行初始化,包括信号量s1、s2等,然后再转入处理调度程序,在进入处理调度程序时,程序并发执行,每当当前进程执行完毕后,记录下当前状态,并标记为等待状态。
然后再由处理器调度程序按随机数再选择一个就绪进程占用处理器运行。
当选取进程后再按照处理器模拟执行程序,通过一个指令计数器来控制执行的指令。
按照实验要求程序的主体部分主要包括进程控制块PCB,模拟处理器操作,以及PV、生产和消费操作等。
1、进程控制块PCB通过程序中的control()函数来进行调度,其中进程的状态有:运行态、就绪态、等待态和完成态。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
模拟PV操作同步机构-且用PV 操作解决生产者——消费者问题。
实验四:同步机构实验报告学院:专业班级:姓名:学号:一、实验内容:模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
二、实验目的:进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实验要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
三、实验题目:模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
四、此次用到的数据结构知识如下:typedef struct Pcb{char name[10]; //进程名char state[10]; //运行状态char reason[10]; //若阻塞,其原因int breakp; //断点保护struct Pcb *next; //阻塞时的顺序进程名状态等待原因断点后继进程}Pcb,*link;进程控制块结构定义两个进程:link p1;//生产者进程,link c1;//消费者进程。
pc程序计数器和link ready; 就绪队列,link b_s1; s1阻塞队列,link b_s2; s2阻塞队列。
五、实验源代码:分为四个头文件。
1、a.h头文件代码如下:#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() */#include <iostream>using namespace std;#include <time.h>#define BUF 10 //缓存的大小#define MAX 20 //最大可以输入的字符2、b.h头文件代码如下://数据结构的定义和全局变量typedef struct Pcb{char name[10]; //进程名char state[10]; //运行状态char reason[10]; //若阻塞,其原因int breakp; //断点保护struct Pcb *next; //阻塞时的顺序}Pcb,*link;int s1,s2; //信号量link p1;//生产者进程link c1;//消费者进程char str[MAX]; //输入的字符串char buffer[BUF]; //缓冲池int len; //输入长度int sp=0; //string的指针int in=0; //生产者指针int out=0; //消费者指针char temp; //供打印的临时产品char rec_p[MAX];//生产记录int rp1=0;//生产记录指针char rec_c[MAX];//消费记录int rp2=0;//消费记录指针link ready; //就绪队列link b_s1; //s1阻塞队列link b_s2; //s2阻塞队列int pc; //程序计数器int count; //字符计数器int con_cnt; //消费计数器3、c.h头文件代码如下:void init(); //初始化void p(int s); //P操作void v(int s); //V操作void block(int s);//阻塞函数void wakeup(int s);//唤醒函数void control(); //处理机调度void processor();//处理机执行void print(); //打印函数void init(){ //初始化s1=BUF;s2=0;p1=(link)malloc(sizeof(Pcb));//建立新的结点,并初始化为生产者strcpy(p1->name,"Producer");strcpy(p1->state,"Ready");strcpy(p1->reason,"Null");p1->breakp=0;p1->next=NULL;c1=(link)malloc(sizeof(Pcb));//建立新的结点,并初始化为消费者strcpy(c1->name,"Consumer");strcpy(c1->state,"Ready");strcpy(c1->reason,"Null");c1->breakp=0;c1->next=NULL;ready=p1;ready->next=c1;//初始化为生产进程在前,消费进程在后c1->next=NULL;b_s1=NULL;b_s2=NULL;//阻塞进程为NULLpc=0;con_cnt=0; //消费计数器}void p(int s){if(s==1){ //p(s1)s1--;if(s1<0)block(1); //阻塞当前生产进程else{printf("\t* s1信号申请成功!\n");ready->breakp=pc; //保存断点}}else{ //p(s2)s2--;if(s2<0)block(2);//阻塞当前消费进程else{printf("\t* s2信号申请成功!\n");ready->breakp=pc; //保存断点}}}void v(int s){if(s==1){ //v(s1)s1++;if(s1<=0)wakeup(1); //唤醒生产进程ready->breakp=pc; //保存断点}else{ //v(s2)s2++;if(s2<=0)wakeup(2);//唤醒消费进程ready->breakp=pc; //保存断点}}void block(int s){//阻塞函数的定义link p;int num1=0;int num2=0;if(s==1){//生产进程strcpy(p1->state,"Block");//改变状态strcpy(p1->reason,"S1");//说明原因p=b_s1;while(p){num1++;p=p->next;//p的值为NULL,表示队尾}if(!b_s1)b_s1=p1;elsep=p1;p1->next=NULL;printf("\t* p1生产进程阻塞了!\n");ready->breakp=pc; //保存断点ready=ready->next;//在就绪队列中去掉,指向下一个num1++;}else{//消费进程strcpy(c1->state,"Block");strcpy(c1->reason,"S2");p=b_s2;while(p){num2++;p=p->next;//p的值为NULL,表示队尾}if(!b_s2)b_s2=c1;elsep=c1;ready->breakp=pc; //保存断点ready=ready->next;//在就绪队列中去掉,指向下一个c1->next=NULL;printf("\t* c1消费进程阻塞了!\n");num2++;}printf("\t* 阻塞的生产进程个数为:%d\n",num1);printf("\t* 阻塞的消费进程个数为:%d\n",num2);}void wakeup(int s){//唤醒函数的定义link p;link q=ready;if(s==1){ //唤醒b_s1队首进程,生产进程队列p=b_s1;b_s1=b_s1->next;//阻塞指针指向下一个阻塞进程strcpy(p->state,"Ready");strcpy(p->reason,"Null");while(q)//插入就绪队列q=q->next;q=p;p->next=NULL;printf("\t* p1生产进程唤醒了!\n");}else{ //唤醒b_s2队首进程,消费进程队列p=b_s2;b_s2=b_s2->next;//阻塞指针指向下一个阻塞进程strcpy(p->state,"Ready");strcpy(p->reason,"Null");while(q->next)//插入就绪队列q=q->next;q->next=p;p->next=NULL;printf("\t* c1消费进程唤醒了!\n");}}void control() //处理器调度程序{int rd;int num=0;link p=ready;if(ready==NULL) //若无就绪进程,结束return;while(p) //统计就绪进程个数{num++;p=p->next;//最终p变为NULL}printf("\t* 就绪进程个数为:%d\n",num);time_t t;srand((unsigned) time(&t));rd=rand()%num;//随机函数产生随机数if(rd==1){p=ready;ready=ready->next;ready->next=p;p->next=NULL;strcpy(ready->state,"Run");strcpy(ready->next->state,"Ready");}elsestrcpy(ready->state,"Run");pc=ready->breakp;}void processor(){ //模拟处理器指令执行if(strcmp(ready->name,"Producer")==0) //当前进程为生产者switch(pc){case 0://produceprintf("\t* 生产者生产了字符%c\n",str[sp]);rec_p[rp1]=str[sp];//添加到生产记录sp=(sp+1)%len;pc++;ready->breakp=pc; //保存断点break;case 1: //p(s1)pc++;p(1);break;case 2: //putbuffer[in]=rec_p[rp1]; //放到缓冲区printf("\t* %c字符成功入驻空缓存!\n",buffer[in]);rp1++;in=(in+1)%BUF;pc++;ready->breakp=pc; //保存断点break;case 3: //v(s2)pc++;printf("\t* 释放一个s2信号\n");v(2);break;case 4://goto01printf("\t* 生产进程goto 0 操作\n");pc=0;count--; //剩余字符个数减1printf("\t* 剩余字符count=%d个\n",count);ready->breakp=pc; //保存断点if(count<=0){ //生产结束printf("\t* 生产者结束生产!\n");strcpy(p1->state,"Stop");strcpy(p1->reason,"Null");ready->breakp=-1;ready=ready->next;//在就绪队列中去掉}}else //当前进程为消费者switch(pc){case 0: //p(s2)pc++;p(2);break;case 1: //getprintf("\t* 消费者取字符!\n");temp=buffer[out];out=(out+1)%BUF;pc++;ready->breakp=pc; //保存断点break;case 2: //v(s1)pc++;printf("\t* 释放一个s1\n");v(1);break;case 3: //consumeprintf("\t* 消费了字符%c\n",temp);rec_c[rp2]=temp;//添加到消费记录rp2++;con_cnt++;if(con_cnt>=len){strcpy(c1->state,"Stop");//完成态c1->breakp=-1;return;}pc++;ready->breakp=pc; //保存断点break;case 4: //goto0printf("\t* 消费进程goto 0 操作\n");pc=0;ready->breakp=pc; //保存断点}}void print(){int i,j;printf("————————生产者消费者模拟———————\n");printf("* 模拟过程的字符串为:\t");printf("%s\n",&str);printf("* 已生产:");for(j=0;j<=rp1;j++)printf("%c",rec_p[j]);printf("\n* 空缓存:");for(j=rp2;j<=rp1;j++)printf("%c",buffer[j]);printf("\n* 已消费:");for(j=0;j<=rp2;j++)printf("%c",rec_c[j]);printf("\n———————进程控制块的信息————————\n");printf("进程名\t\t状态\t等待原因\t断点\n");printf("%s\t%s\t%s\t\t%d\n\n",p1->name,p1->state,p1->reason,p1->b reakp);printf("%s\t%s\t%s\t\t%d\n",c1->name,c1->state,c1->reason,c1->bre akp);printf("———————————————————————\n");printf("1.继续 0.退出\n");scanf("%d",&i);if(i==0){exit(0);}}4、main头文件代码如下:#include "a.h"#include "b.h"#include "c.h"void main(){printf("*生产者消费者模拟\n");printf("—————————\n");printf("*请输入字符串:\n");scanf("%s",str); //string数组存放将要产生的字符len=strlen(str);count=len; //输入字符的个数init(); //初始化while(con_cnt<len) //消费完所有的字符为结束{system("cls"); //清屏操作printf("—————————模拟指令流程————————\n");control(); //处理器调度程序processor(); //模拟处理器指令执行print(); //输出显示各个信息}printf("\n程序结束!\n");}六、运行结果截图:。