同步与互斥问题解决方案--例题
第4章 并发性:互斥和同步

哲学家进餐问题
管程
管程是一种程序设计语言结构
– 并发Pascal,Pascal-plus,Modula-2, Modula-3和Java等
主要特点:
– 本地变量只能由管程过程访问 – 进程通过调用管程过程进入管程 – 一次只能有一个管程过程在执行(实现互斥) 实现
管程(续)
通过cwait(c), csignal(c) 操作 管程中的条件 变量实现同步
有界缓冲区生产者/消费者问题的 管程解决方案
有界缓冲区生产者/消费者问题的 管程解决方案
消息传递
消息传递是相互合作的并发进程交换信 息的一种高级通信方式
– 进程间的数据交换以消息为单位
基于消息传递原语实现通信:
– 发送消息原语 send(destination, message) – 接收消息原语 receive(source, message)
临界区
二,专门的机器指令
适用范围(前提)
– 单处理器或共享主存多处理器结构 – 对同一存储单元的访问是互斥的
Dekker算法第二种尝试失败的原因
– 如果测 flag[1] 和置位 flag[0] 在一个指令周 期完成就不会出错
Testset 指令 (Test and Set---TS)
定义(逻辑)
boolean testset (int i) { if (i == 0) { i = l; return true; } else return false; }
一个指令周期完成,不会被中断
exchange指令
定义(逻辑)
void exchange(int register, int memory) { int temp; temp = memory; memory = register; register =temp ; }
进程同步与互斥应用例子

数据库
写者 { 写数据库; }
读者 { 读数据库; }
进程的互斥
分析:写进程writer、读进程reader因竞争数据库这个资源
而成为互斥关系。因为写进程执行时,不能执行其他读写 进程,所以还必须设置一个计数器统计读进程的个数。如 果是第一个读进程,就与写进程竞争数据库。如果是最后 一个读进程,就释放数据库。因计数器是一个临界资源, 所以多个读进程对计数器的操作又是互斥操作。
进程的同步
解:这是一个同步问题,信号量初值:S2=0,S3=0,S4=0, S5=0,S6=0
进程P1 执行P1 V(S2) V(S3) 进程P4 P(S4) 执行P4 V(S6) 进程P2 P(S2) 执行P2 V(S4) 进程P5 P(S5) 执行P5 V(S6) 进程P3 P(S3) 执行P3 V(S5) 进程P6 P(S6) P(S6) 执行P6
进程的同步
• 例1:假设有三个并发进程P,Q,R,其中P负责从输入设 备上读入信息并传送给Q,Q将信息加工后传送给R,R则负 责将信息打印输出。进程P、Q共享一个缓冲区,进程Q、R 共享另一个缓冲区。
3个进程P、Q、R P进程: 从输入设备上读入信息 将信息放入缓冲区1 Q进程: 从缓冲区1取出信息 将信息放入缓冲区2中 R进程: 从缓冲区2取出信息 将信息打印输出
进程的互斥
练习:过十字路口(单道)。
P4
P1
P3
P2
P1 { 通过路口; }
P2 { 通过路口; }
P3 { 通过路口; }
P4
{ 通过路口; }
进程的互斥
分析:进程P1、P2、P3、P4因竞争十字路口这个资源而成 为互斥关系。 设:信号量m表示十字路口资源,初值为1表示资源可用。
进程的同步与互斥

例题:选择题1、当一个进程独占处理器执行时,具有两个特性,即()。
A、封闭性和可再现性B、独立性和可再现性C、开放性和可再现性D、顺序性和独立性2、对于两个并发进程,设互斥信号量为A,若A=0,则()。
A、表示有一个进程进入临界区,另一个进程等待进入B、表示有两个进程进入临界区C、表示有一个进程进入临界区D、表示没有进程进入临界区3、进程并发执行时,执行结果与其执行的()有关。
A、绝对速度B、时间C、速度D、相对速度4、造成进程结果不正确的因素与进程占用处理器的时间、执行的速度及外界的影响有关。
而这些因素都与时间有关,所以称为()。
A、时间因素B、与时间有关的错误C、时间错误D、时间问题5、P、V操作是对()进行操作。
A、信号量B、执行速度C、执行时间D、执行结果5、两个进程合作完成一个任务,在并发执行中,一个进程要等待其合作伙伴发来消息,或者建立某个条件后再向前执行,这种制约性合作关系被称为进程的()。
A、调度B、执行C、同步D、互斥6、信号量被定义为一个整型变量,其初始值是()。
A、0B、无任何限制C、负整数D、非负数填空题:1、并发进程间的关系可以是()的,也可以是有()的。
2、在用P、V操作实现同步时,一定要根据具体的问题来定义()和调用()。
3、每执行一次P原语操作,信号量s的数值减1,如果s>=0,该进程();若s<0,则()该进程,并把它插入该()对应的()队列中,重新进行进程调度。
综合应用题1、假定有三个进程R、W1、W2共享一个缓冲器B,而B中每次只能存放一个数。
当缓冲器中无数时,进程R可将M输入设备上读入的数存放到缓冲器B中;若存放到缓冲器中的是奇数,则允许进程W1将其取出打印;若存放到缓冲器中的是偶数,则允许进程W2将其取出打印。
同时规定:进程R必须等缓冲器中的数被取出打印后才能再存放一个数;进程W1或W2对每次存入缓冲器中的数只能打印一次;W1和W2都不能从空的缓冲器中取数。
实验四同步与互斥Linux实验报告

实验四同步与互斥【实验目的和要求】1、掌握进程(线程)的同步与互斥。
2、掌握生产者消费者问题的实现方法。
3、掌握多线程编程方法。
【实验内容】实现生产者消费者问题1、有一个仓库,生产者负责生产产品,并放入仓库,消费者会从仓库中拿走产品(消费)。
2、仓库中每次只能入一个(生产者或消费者)。
3、仓库中可存放产品的数量最多10个,当仓库放满时,生产者不能再放入产品。
4、当仓库空时,消费者不能从中取出产品。
5、生产、消费速度不同。
【实验原理】1、信号量mutex提供对缓冲池访问的互斥要求并初始化为1,信号量empty和full分别用来表示空缓冲项和满缓冲项的个数,信号量empty初始化为n,信号量full初始化为0。
2、定义如下结构及数据:定义缓冲区内的数据类型:typedef int buffer_item;缓冲区:buffer_item buffer[BUFFER_SIZE];对缓冲区操作的变量:int in,out;信号量mutex提供了对缓冲池访问的互斥要求:pthread_mutex_t mutex;信号量empty和full分别表示空缓冲顶和满缓冲顶的个数:sem_t empty,full; 可以设定生产者的生产速度及消费者的消费速度:int pro_speed,con_speed;对缓冲区操作的自增函数:#define inc(k) if(k < BUFFER_SIZE) k = k+1;else k=03、并定义了如下实现问题的函数模块:将生产的产品放入缓冲区: int insert_item(buffer_item item)从缓冲区内移走一个产品: int remove_item(buffer_item *item)生产者进程:void *producer(void *param)消费者进程:void *consumer(void *param)生产者结构进程消费者结构进程【程序代码】//sx.c#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<semaphore.h>#include<time.h>#define inc(k) if(k<BUFFER_SIZE) k=k+1;else k=0#define BUFFER_SIZE 10//缓冲区的大小typedef int buffer_item;//定义缓冲区内的数据类型buffer_item buffer[BUFFER_SIZE];//缓冲区int in,out;//对缓冲区操作的变量pthread_mutex_t mutex;//信号量mutex提供了对缓冲池访问的互斥要求sem_t empty,full;//信号量empty和full分别表示空缓冲顶和满缓冲顶的个数int pro_speed,con_speed;//可以设定生产者的生产速度及消费者的消费速度int insert_item(buffer_item item){//将生产的产品放入缓冲区buffer[in]=item;printf("******insert缓冲池第%d号******\n",in);inc(in);}int remove_item(buffer_item *item){//从缓冲区内移走一个产品*item = buffer[out];printf("******remove缓冲池第%d号******\n",out);inc(out);}void *producer(void *param){//生产者进程buffer_item item;int num = 0;while(1){sleep(rand()%(16-pro_speed));printf("\n******第%d次生产******\n",++num);printf("******等待empty信号******\n");sem_wait(&empty);printf("******等待解锁******\n");pthread_mutex_lock(&mutex);printf("******上锁,准备生产******\n");item = rand()%1000+1;printf("******生产产品%d*******\n",item);insert_item(item);printf("*******解锁******\n");printf("******第%d次生产结束*******\n\n",num); pthread_mutex_unlock(&mutex);sem_post(&full);}}void *consumer(void *param){//消费者进程buffer_item item;int num = 0;while(1){sleep(rand()%(16-con_speed));printf("\n******第%d次消费*****\n",++num); printf("******等待full信号******\n");sem_wait(&full);printf("******等待解锁******\n");pthread_mutex_lock(&mutex);printf("******上锁,准备消费******\n"); remove_item(&item);pthread_mutex_unlock(&mutex);sem_post(&empty);printf("******消费产品%d*******\n",item);printf("*******解锁******\n");printf("******第%d次消费结束*******\n\n",num); }}int main()//主函数{pthread_t tid1,tid2;pthread_attr_t attr1,attr2;srand(time(NULL));pthread_mutex_init(&mutex,NULL);//初始化sem_init(&empty,0,BUFFER_SIZE);sem_init(&full,0,0);in=0;out=0;printf("***********************\n");printf("********开始!***********\n");printf("***********************\n");printf("生产者速度(1-15):\n");scanf("%d",&pro_speed);printf("消费者速度(1-15):\n");scanf("%d",&con_speed);pthread_attr_init(&attr1);pthread_create(&tid1,&attr1,producer,NULL);pthread_attr_init(&attr2);pthread_create(&tid2,&attr2,consumer,NULL);sleep(100);printf("*******程序over*******\n");return 0;}【实验步骤】编写程序代码gedit sx.c,再对代码进行编译gcc sx.c –o sx –lpthread,编译无错误,进行运行./sx,根据提示要求进行填写生产者和消费速度,观察消费者和生产者进程。
操作系统精髓与设计原理-第5章 并发性_互斥和同步

第五章并发性:互斥和同步复习题:5.1列出与并发相关的四种设计问题答:进程间的交互,共享资源之间的竞争,多个进程的同步问题,对进程的处理器时间分配问题5.2列出并发的三种上下文答:多个应用程序,结构化应用程序,操作系统结构5.3执行并发进程的最基本要求是什么?答:加强互斥的能力5.4列出进程间的三种互相知道的程度,并简单地给出各自的定义。
答:进程间互相不知道对方:这是一些独立的进程,他们不会一起工作。
进程间间接知道对方:这些进程并不需要知道对方的进程ID号,但他们共享访问某些对象,如一个I/O缓冲区。
进程间直接知道对方:这些进程可以通过进程ID号互相通信,用于合作完成某些活动。
5.5竞争进程和合作进程进程间有什么区别。
答:竞争进程需要同时访问相同的资源,像磁盘,文件或打印机。
合作进程要么共享访问一个共有的资源,像一个内存访问区,要么就与其他进程相互通信,在一些应用程序或活动上进行合作。
5.6列出与竞争进程相关的三种控制问题,并简单地给出各自的定义。
答:互斥:竞争进程仅可以访问一个临界资源(一次仅有一个进程可以访问临界资源),并发机制必须满足一次只有一个进程可以访问临界资源这个规则。
死锁:如果竞争进程需要唯一的访问多于一个资源,并且当一个进程控制着一个进程,且在等待另一个进程,死锁可能发生。
饥饿:一组进程的一个可能会无限期地拒绝进入到一个需要资源,因为其他成员组成垄断这个资源。
5.7列出对互斥的要求。
答:1.必须强制实施互斥:在具有关于相同资源或共享对象的临界区的所有进程中,一次只允许一个进程进入临界区。
2.一个在临界区停止的进程必须不干涉其他进程。
3.绝不允许出现一个需要访问临界区的进程被无限延迟的情况,即不会饿死或饥饿。
4.当没有进程在临界区中时,任何需要进入临界区的进程必须能够立即进入。
5.对相关进程的速度和处理器的数目没有任何要求和限制。
6.一个进程驻留在临界区中的时间是有限的。
5.8在信号量上可以执行什么操作。
多线程同步与互斥 方法

多线程同步与互斥方法
多线程同步和互斥是为了保证多个线程能够安全地访问共享资源而采取的措施。
下面是几种常见的多线程同步与互斥的方法:
1. 锁(lock):通过加锁的方式来保护临界区,只有获得锁的线程才能进入临界区执行代码,其他线程需要等待锁的释放。
常见的锁包括互斥锁(mutex)和读写锁(read-write lock)。
2. 信号量(semaphore):允许多个线程同时访问某个资源,但要限制同时访问的线程数量,通过信号量进行计数来实现。
3. 条件变量(condition variable):允许线程在某个条件满足时等待,直到其他线程发出信号通知它们继续执行。
4. 互斥量(mutex):一种特殊的锁,用于确保某段代码只能被一个线程执行,其他线程需要等待。
5. 读写锁(read-write lock):允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。
6. 自旋锁(spin lock):不会引起线程的阻塞,在尝试获取锁时,会一直处于循环中直到获取到锁为止。
7. 可重入锁(reentrant lock):允许同一线程多次获取同一个锁而不会发生死锁。
以上方法都是为了解决多线程之间的冲突和竞争条件问题,保证线程安全和数据一致性。
根据具体的场景和需求,选择适合的同步与互斥方法可以提高多线程程序的性能和正确性。
并发性:互斥和同步

此两种进程必须遵循一定的规则
利用信号量实现进程同步-2
• 为了实现进程同步,需采用同步信号量。 • 设置一个同步信号量full,它代表的资源是缓冲器满,它 的初值为0。这个资源是Print进程所拥有,Print进程可以 申请该资源,对它施加P操作,如条件满足Print进程可从 Buffer中取数。而Print进程的合作进程Compute对full信号 量施加V操作,即它可释放该资源。当Compute进程将数 据存入Buffer后,即可释放该资源供Print进程再使用。 • 设置另一个同步信号量empty,它代表的资源是缓冲器空, 它的初值为1 。缓冲器空这个资源是进程Compute所拥有, 它可以申请该资源,对它施加Print操作。而它的合作进程 Print对empty信号量施加V操作。
5.5 读者/写者问题
• 一个数据集(如文件)如果被几个并行进程所共享,有些 一个数据集(如文件)如果被几个并行进程所共享, 进程只要求读数据集内容,它称读者, 进程只要求读数据集内容,它称读者,而另一些进程则要 求修改数据集内容,它称写者, 求修改数据集内容,它称写者,几个读者可以同时读些数 据集,而不需要互斥,但一个写者不能和其它进程( 据集,而不需要互斥,但一个写者不能和其它进程(不管 是写者或读者)同时访问些数据集,它们之间必须互斥。 是写者或读者)同时访问些数据集,它们之间必须互斥。 • 设置互斥信号量 信号量wmutex 表示写者间、读者和写者间互 表示写者间、 设置互斥信号量 读者和写者主要程序如下 程序如下: 斥,读者和写者主要程序如下: reader: writer: 第一个读者到时P( P(wmutex) 第一个读者到时 (wmutex) ) ( ) Read Text Write Text 最后一个读者离开时 一个读者离开时V( V(wmutex) 最后一个读者离开时 (wmutex) ) (
用信号量机制来解决进程的同步与互斥:PV操作

用信号量机制来解决进程的同步与互斥:PV操作首先确定进程间的关系,然后确定信号量及其值。
判断进程间是否互斥的关键:看进程间是否共享某一公有资源,一个公有资源与一个信号量相对应。
确定信号量的值是一个关键点,它代表了可用资源实体数。
举例:票大厅容纳的人数限制为20人,少于20人时购票者可以进入,否则要在厅外等候。
进程间是同步时:是否存在合作关系,是否需要互通消息首先判断进程间的关系为同步的,且为各并发进程设置私有信号量,然后为私有信号量赋初值,最后利用PV原语和私有信号量规定各进程的执行顺序。
举例:公交车上司机与售票员的行为,司机到站停车后,售票员方可开门,售票员关门后,司机方可开车。
进程同步应用示例讲解:1桌上有一个盘子,可以存放一个水果。
父亲总是把苹果放在盘子中,母亲总是把香蕉放在盘子中;一个儿子专等吃盘中的香蕉,一个女儿专等吃盘中的苹果。
1)系统要设几个进程来完成这个任务?各自的工作是什么?2)这些进程间有什么样的相互制约关系?3)用P,V操作写出这些进程的同步算法(注:标明信号量的含义)。
1)需要四个进程进程描述:Father:父亲放置苹果的进程;Mother:母亲放置香蕉的进程;Son:儿子吃香蕉的进程;Daughter:女儿吃苹果的进程。
分析:四人公用一个盘子;盘子每次只能放一个水果,当盘子为空时,父母均可尝试放水果,但一次只能有一人成功;盘中是香蕉,儿子吃,女儿等;盘中是苹果,女儿吃,儿子等。
2)进程之间既有互斥又有同步关系。
Father进程和Mother进程要互斥的向盘中放水果,应设置一互斥信号量dish,初值为1,表示盘子为空;Father进程要设置同步信号量apple,用于给Daughter进程传送消息,初值为0,表示还没有消息产生,即没有放苹果;相应Daughter进程也要向父、母进程传送盘子为空的消息。
Mother进程要设置同步信号量banana,用于给Son进程传送消息,初值为0,表示还没有消息产生,即没有放香蕉。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
写者: While(true){
P(w); 写 V题: 写者优先 条件: 1)多个读者可以同时进行读 2)写者必须互斥(只允许一个写者写,也 不能读者写者同时进行) 3)写者优先于读者(一旦有写者,则后续 读者必须等待,唤醒时优先考虑写者)
readcount=0; writecount=0; S=mutex=w=wmutex=1 读者: while (true) { P(S); P(mutex); readcount ++; if (readcount==1) P (w); V(mutex); V(S); 写者: while (true) { P(wmutex); writecount++; if(writecount==1) P(S); V(wmutex); P(w); 写 V(w); P(wmutex); writecount--; if(writecount=0) V(S); V(wmutex); };
读
P(mutex); readcount --; if (readcount==0) V(w); V(mutex);
继续
• 在实际应用中,写优先非常重要,因为写 代表的是对数据的更新。而我们希望读到 的是最新的消息。因此继续进行改进,就 要考虑,如果写者到来,可以让正在读的 读者让路,先让写者写。
– 无读者、写者,新读者可以读 – 有写者等待,但有其他读者正在读,新读者可以读 – 有写者写,新读者等
• 如果写者来:
– 无读者,新写者可以写 – 有读者,新写者等待 – 有其他写者,新写者等待
读者: While(true){ P(mutex); readcount++; if(readcount==1) P(w); V(mutex); 读 P(mutex); readcount--; if(readcount==0) V(w); V(mutex); }
读者写者问题
经典同步互斥问题: 读者/写者问题
• 读者/写者问题
– 读者/写者进程共享相同的数据区域. – 读者进程读共享数据区. – 写者进程更新(读或写)共享数据区.
• 同步与互斥需求
– 写者不能与其它进程同时访问共享数据区. – 多个读进程可以同时访问共享的数据区.
读者优先
• 如果读者来:
读
P(mutex); readcount --; if (readcount==0) V(w); V(mutex); };
分析
• S的意义? • 上面代表的情形 • 能否继续对写者进行提前?
readcount=0; writecount=0;S=mutex=w=wmutex=m=1 读者: while (true) { P(m); P(S); P(mutex); readcount ++; if (readcount==1) P (w); V(mutex); V(S); V(m); 写者: while (true) { P(wmutex); writecount++; if(writecount==1) P(S); V(wmutex); P(w); 写 V(w); P(wmutex); writecount--; if(writecount=0) V(S); V(wmutex); };
理发师问题
• 理发店理有一位理发师、一把理发椅和 n 把供等候理发的顾客坐的椅子 • 如果没有顾客,理发师便在理发椅上睡觉 • 一个顾客到来时,它必须叫醒理发师 • 如果理发师正在理发时又有顾客来到,则
如果有空椅子可坐,就坐下来等待,否则
就离开
设置整形变量 waiting /*等候理发的顾客数*/ CHAIRS /*为顾客准备的椅子数*/ 信号量 customers顾客数, barbers空着的理发师数,mutex customers = 0; barbers = 0; waiting = 0; mutex = 1; Procedure barber; while(TRUE){ /*理完一人,还有顾客吗?*/ P(cutomers); /*若无顾客,理发师睡眠*/ P(mutex); /*进程互斥*/ waiting = waiting – 1; /*等候顾客数少一个*/ V(barbers); /*理发师去为一个顾客理发*/ V(mutex); /*开放临界区*/ cut-hair( ); /*正在理发*/ } procedure customer { P(mutex); /*进程互斥*/ if waiting<CHAIRS{ /*看看有没有空椅子*/ waiting = waiting+1; /* 等候顾客数加1*/ V(customers); /*必要的话唤醒理发师*/ V(mutex); /*开放临界区*/ P(barbers); /*无理发师, 顾客坐着养神*/ get-haircut( ); /*理发*/ } else V(mutex); /*人满了,走吧!*/ }