北航操作系统课程-第七、八次作业-进程同步

北航操作系统课程-第七、八次作业-进程同步


北京航空航天大学计算机学院-2020春操作系统课程
题目作者为北航计算机学院操作系统课程组,答案为博主原创。水平有限,无法保证作答正确性,如有错误敬请批评指正。部分作答源自百度谷歌等其他资料,如有侵权联系删除


1 三个进程 P1、P2、P3 互斥使用一个包含 N(N>0)个 单元的缓冲区。P1 每次用 produce() 生成一个正整数并用 put() 送入缓冲区某一个空单元中;P2 每次用 getodd() 从该缓冲区中取出一个奇数并用 countodd() 统计奇数个数;P3 每次用 geteven() 从该缓冲区中取出一个偶数并用 counteven() 统计偶数个数。请用信号量机制实现这三个进程的同步与互斥活动,并说明所定义的信号量的含义。

缓冲区是三个进程的共享空间,对其访问需要信号量保护,设为 mutex,初值为 1

P1、P2共享缓冲区中的奇数,奇数的个数需要统计,用信号量 odd 表示,初值为 0;P1、P3共享缓冲区中的偶数,偶数的个数需要统计,用信号量 even 表示,初值为 0

缓冲区满时 P1 不能再送入整数,缓冲区的空位数需要统计,用信号量 empty 表示,初值为 N

三个进程操作缓冲区前后都进行 P(mutex) 和 V(mutex) 操作,mutex 对缓冲区加锁以保证不会冲突,缓冲区操作完后释放锁;P1 将整数送入缓冲区时进行 P(empty),消耗缓冲区的空位,以保证没有空位时不再送入整数,同时每次送入数根据奇偶执行 V(odd) 或 V(even) 之一的操作,增加奇数和偶数的数量;P2 每次获取奇数时进行 P(odd) ,随后进行 V(empty),P3 每次获取偶数时进行 P(even) ,随后进行 V(empty)。

Semaphore mutex = 1, odd = 0, even = 1, empty = N;

P1:
while(true) {
    P(empty);
    integer = produce();
    P(mutex);
    	put();
    V(mutex);
    if (integer % 2 == 0) 
        V(even);
    else
        V(odd);
}

P2:
while(true) {
    P(odd);
    P(mutex);
    	gedodd();
    V(mutex);
    V(empty);
    countodd();
}

P3:
while(true) {
    P(even);
    P(mutex);
    	gedeven();
    V(mutex);
    V(empty);
    counteven();
}

2 一个野人部落从一个大锅中一起吃炖肉,这个大锅一次可以存放 M 人份的炖肉。当野人们想吃的时候,如果锅中不空,他们就自助着从大锅中吃肉。如果大锅空了,他们就叫醒厨师,等待厨师再做一锅肉。

野人线程未同步的代码如下:

while(true) {
	getServingFromPot()eat();
}

厨师线程未同步的代码如下:

while(true) {
	putServingsInPot(M);
}

同步的要求是:当大锅空的时候,野人不能够调用 getServingFromPot();仅当大锅为空的时候,大厨才能够调用 putServingsInPot()。问题:请写出满足同步要求的野人线程和厨师线程的同步原语。

野人在没有食物的时候需要阻塞等待,厨师在有食物的时候需要阻塞等待,因此用两个信号量 isEmpty 和 haveFood 分别表示厨师阻塞等待和野人阻塞等待的条件,初始状态没有食物。使用普通类型变量 food 监控食物剩余量。havefood 信号量保证每次只有一个野人操作锅里的食物以及 food 变量,在一个野人进程获取一份食物后,其判定锅里是否还有食物,若还有食物则唤醒其他野人进程,若没有食物则唤醒厨师进程。

Semaphore isEmpty = 1, haveFood = 0;
int food = 0;

Savages:
while(true) {
    P(haveFood);
    getServingFromPot();
    food--;
    if (food == 0)
        V(isEmpty);
    else
        V(haveFood);
    eat();
}

Cook:
while(true) {
    P(isEmpty);
    putServingInPot(M);
    food += M;
    V(haveFood);
}

3 系统中有多个生产者进程和消费者进程,共享用一个可以存 1000 个产品的缓冲区(初始为空),当缓冲区为未满时,生产者进程可以放入一件其生产的产品,否则等待;当缓冲区为未空时,消费者进程可以取走一件产品,否则等待。要求一个消费者进程从缓冲区连续取出 10 件产品后,其他消费者进程才可以取产品,请用信号量 P, V 操作实现进程间的互斥和同步,要求写出完整的过程,并指出所用信号量的含义和初值。

题目规定一个消费者连续取出 10 件产品后才能改由其他消费者取产品,那么直接在生产者-消费者模型基础上让每个消费者连续取 10 次,而该消费者取 10 次期间别的消费者不能打扰,设定信号量 lock 来保护连续取产品的过程,而生产者不受 lock 信号量的约束。

Semaphore mutex = 1, empty = 1000, product = 0, lock = 1;

Consumer:
while(true) {
    P(lock);
    for (int i = 0; i < 10; i++) {
        P(product);
    	P(mutex);
    		consume();
    	V(mutex);
        V(empty);
    }
    V(lock);
}

Producer:
while(true) {
    P(empty);
    P(mutex);
    	produce();
    V(mutex);
    V(product);
}

1 读者写者问题的写者优先算法 : 1)共享读; 2)互斥写、读写互斥; 3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)。

Semaphore write_write = 1;		// 保证写-写互斥
Semaphore read_write = 1;		// 保证读-写互斥
Semaphore writers_mutex = 1;	// 保证访问共享变量writers互斥
Semaphore readers_mutex = 1;	// 保证访问共享变量readers互斥
Semaphore write_pendings = 1;	// 保证写者优先于读者
int writers = 0, readers = 0;	// 计数写者和读者的数量

Readers:
while(true) {
    P(write_pending);
	P(read_write); 
    P(readers_mutex);
		readers++; 
    	if (readers == 1)
            P(write_write); 
    V(readers_mutex); 
    V(read_write); 
    V(write_pending);
    read();
    P(readers_mutex);
    	readers--; 
    	if (readers == 0)
			V(write_write);
	V(readers_mutex);
}

Writers:
while(true) {
    P(writers_mutex);
    	writers++; 
    	if (writers == 1)
            P(read_write); 
    V(writers_mutex); 
    P(write_write);
    	write();
    V(write_write); 
    P(writers_mutex);
		writers--; 
    	if (writers == 0)
            V(readBlock);
	V(writers_mutex);
}

2 寿司店问题。假设一个寿司店有5 个座位,如果你到达的时候有一个空座位,你可以立刻就坐。但是如果你到达的时候5 个座位都是满的有人已经就坐,这就意味着这些人都是一起来吃饭的,那么你需要等待所有的人一起离开才能就坐。编写同步原语,实现这个场景的约束。

Semaphore mutex = 1; 	// 保证客人到达与离开时计算的互斥
Semaphore block = 0; 	// 用于等待队列
bool must_wait = False; // 为真表示寿司店已满需等待
int eating = 0; 		// 记录在寿司店就餐的线程数
int waiting = 0; 		// 记录在寿司店等待的线程数

while (true) {
    P(mutex); 
    if(must_wait) {
        waiting++; 
        V(mutex);
        P(block);
    } else {
        eating++;
        if (eating == 5)
            must_wait = true;
        else must_wait = false;
        V(mutex);
    }
    sit_and_eat();
    P(mutex);
    eating--; 
    if (eating == 0) {
        int n = min(5, waiting);
        waiting -= n;
        eating += n; 
        if (eating == 5) 
            must_wait = True;
		else must_wait = False;
        while(n--)
            V(block);
    }
    V(mutex);
}

3 搜索-插入-删除问题。三个线程对一个单链表进行并发的访问,分别进行搜索、插入和删除。搜索线程仅仅读取链表,因此多个搜索线程可以并发。插入线程把数据项插入到链表最后的位置;多个插入线程必须互斥防止同时执行插入操作。但是,一个插入线程可以和多个搜索线程并发执行。最后,删除线程可以从链表中任何一个位置删除数据。一次只能有一个删除线程执行;删除线程之间,删除线程和搜索线程,删除线程和插入线程都不能同时执行。请编写三类线程的同步互斥代码,描述这种三路的分类互斥问题。

Semaphore search_search = 1; 	// 确保搜索线程之间互斥访问
Semaphore search_delate = 1; 	// 确保搜索线程与删除线程之间互斥
Semaphore insert_insert = 1; 	// 确保插入线程之间互斥
Semaphore insert_delate = 1;  	// 确保插入线程与删除线程之间互斥
int searchers = 0; 				// 记录搜索线程数量
int inserters = 0;   			// 记录插入线程数量

Seachers:
while(true) {
	P(search_search); 
    	searchers++;
		if (searchers == 1)
       		P(search_delate);
	V(search_search);
	search();
    P(search_search); 
    	searchers--;
		if (searcher == 0)
            V(search_delate);
	V(search_search);
}

Inserters:
while(true) {
	P(insert_insert); 
    	inserters++;
		if (inserters == 1)
            P(insert_delate);
	V(insert_insert); 
    P(insert_insert);
		insert();
    V(insert_insert); 
    P(insert_insert);
		if (inserters == 0)
            V(insert_delate);
	V(insert_insert);
}

Deleters:
while(true) {
	P(search_delate); 
    P(insert_delate);
		delate();
    V(insert_delate); 
    V(search_delate);
}


4 一个系统有 4 个进程和 5 个可分配资源,当前分配和最大需求如下:

进程已分配资源最大需求可用资源
进程A102111121300x12
进程B2011022210
进程C1101021310
进程D1111011221

若保持该状态是安全状态,那么 x 的最小值是多少?

各进程资源需求矩阵如下:

A 01002
B 02100
C 10300
D 00111

分析 x:

若 x 为 0,资源无法满足任何进程的需求,系统立刻进入不安全状态;

若 x 为 1,进程 D 可分配资源首先运行,D 结束后可用资源向量为 11222,进程 A 可分配资源运行,结束后可用资源向量为 21433,此时进程 C 可分配资源运行,C 结束后可用资源向量为 32443,可满足进程 B 需求,所有进程运行完毕。

故 x 最小值为 1。

  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
三个进程P1,P2,P3,以及有N(>1)个单元的缓冲区。P1调用produce()产生一个整数,调用put()将其放入缓冲区。P2调用getodd()从缓冲区取出一个奇数,然后调用countodd()计算奇数的个数;P2调用geteven()从缓冲区取出一个偶数,然后调用counteven()计算偶数的个数。用信号量机制实现进程同步 使用到的函数和信号量 HANDLE mutex; HANDLE empty; HANDLE full; 创建信号量 HANDLE CreateSemaphore( __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,// lpSemaphoreAttributes是信号量的安全属性 可为NULL __in LONG lInitialCount,// lInitialCount是初始化的信号量 __in LONG lMaximumCount,// lMaximumCount是允许信号量增加到最大值 __in_opt LPCWSTR lpName//lpName是信号量的名称 可为NULL ); 创建互斥信号量 HANDLE CreateMutex(  LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针 可为NULL  BOOL bInitialOwner, // 初始化互斥对象的所有者  LPCTSTR lpName // 指向互斥对象名的指针 ); 申请一个资源 WaitForSingleObject(HANDLE full,INFINITE); 释放资源 ReleaseSemaphore( __in HANDLE hSemaphore,// hSemaphore是要增加的信号量句柄 __in LONG lReleaseCount,// lReleaseCount是增加的计数。 __out_opt LPLONG lpPreviousCount//lpPreviousCount是增加前的数值返回。 ); 释放互斥信号量 BOOL ReleaseMutex(HANDLE hMutex); DWORD WaitForMultipleObjects( DWORD nCount, // number of handles in array CONST HANDLE *lpHandles, // object-handle array BOOL bWaitAll, // wait option DWORD dwMilliseconds // time-out interval );

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值