Os-作业四:进程
作业四:进程
20373915-朱文涛
读者写者问题(写者优先)
题目:满足以下条件的读者写者问题:
-
读者可以共享;
-
读写互斥、写写互斥;
-
写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)
答:如下述伪代码所示,重要部分注释:
semaphore mutex_for_reader_count = 1; //用于写reader_count互斥
semaphore mutex_for_writer_count = 1; //用于写writer_count互斥
int reader_count = 0;
int writer_count = 0;
semaphore mutex = 1; //*************** 共享文件锁 **************
semaphore mutex_for_write = 1; //用于实现同时最多一个写者写
semaphore mutex_for_read = 1; //用于实现读者正真的优先
Reader() {
while(1) {
P(mutex_for_read);//
P(mutex);//没有写者在写时可以进行读
P(mutex_for_reader_count); //互斥访问reader_count变量
if (reader_count == 0) { //如果是第一个读进程访问共享变量
P(mutex_for_write); //阻止写进程写
}
reader_count++;
V(mutex_for_reader_count); //释放互斥变量reader_count
V(mutex); //恢复对共享文件的访问(可以多读者共享)
V(mutex_for_read);
-----------------------------------
read_something();
-----------------------------------
P(mutex_for_reader_count); //读完读者离开
reader_count--;
if (reader_count == 0) {
V(mutex_for_write); //如果已经无读者,释放写进程锁,使写进程可写
}
V(mutex_for_reader_count);
}
}
/*
分析写者优先:
1:对于写者,如果拿到了mutex锁,则不允许其他读文件读,同时mutex_for_write保证最多一个写着写
2:假定写者写操作时,来了若干读者,最后来了写者,由于write_count++,故写进程不会释放mutex锁,达到类似于 优先唤醒写进程的工作,此时写进程阻塞在mutex_for_write队列中,等到当前写进程写完,便可优先写
3:例如一个读者释放mutex锁,此时多读者进程和写进程争抢mutex锁,加入mutex_for_read锁,使其余读者在 mutex_for_read前阻塞排队,防止被阻塞的一些读进程排在写进程前面。
*/
Writer() {
P(mutex_for_writer_count);//互斥访问reader_count变量
if (writer_count == 0) { //如果是第一个写进程写共享文件
P(mutex); //阻止读操作
}
writer_count++;
V(mutex_for_writer_count);
P(mutex_for_write); //阻止写操作
-----------------------------------
write_something();
-----------------------------------
V(mutex_for_write);
P(mutex_for_writer_count); //写完写者离开
writer_count--;
if (writer_count == 0) {
V(mutex); //如果无写者,恢复共享文件
}
V(mutex_for_writer_count);
}
寿司店问题
题目:假设一个寿司店有5个座位,如果顾客到达的时候有一个空座位,顾客可以立刻就坐。但是如果顾客到达的时候5个座位都是满的有人已经就坐,这就意味着这些人都是一起来吃饭的,那么顾客需要等待所有的人一起离开才能就坐。编写同步原语,实现这个场景的约束。
答:如下述伪代码所示,重要部分注释:
semaphore mutex = 1; //锁,互斥对各变量的修改*
semaphore VIP_ROME = 0;
int number_eating = 0;
int number_waiting = 0;
bool need_wait = false
//来到饭店,判断等待情况
P(mutex);
if need_wait: //需要等待所有人离开
number_waiting ++;
V(mutex);
P(VIP_ROOM); //在贵宾室等待
else: //可以直接吃,如果就坐后满了,后续需要等待
number_eating ++;
need_wait = (eating == 5);
V(mutex);
//开始大快朵颐
eating_AoLiGei();
//吃完跑路
P(mutex);
number_eating --; //吃完了
if number_eating == 0: //如果最后一个顾客,可唤醒VIP_ROOM上等待的顾客
number_can_eating = min(5, waiting); //最多5个顾客可以吃
number_waiting -= number_can_eating;
number_eating += number_can_eating;
need_wait = (number_eating == 5);
for (int i = 0; i < number_can_eating; i++) {
V(VIP_ROOM); //叫等待的人来进餐
}
V(mutex);
生产者-消费者模型
题目:三个进程 P1、P2、P3 互斥使用一个包含 N(N>0)个单元的缓冲区。P1 每次用 produce()生成一个正整数并用 put()送入缓冲区某一个空单元中;P2 每次用 getodd()从该缓冲区中取出一个奇数并用 countodd()统计奇数个数;P3 每次用 geteven()从该缓冲区中取出一个偶数并用 counteven()统计偶数个数。请用信号量机制实现这三个进程的同步与互斥活动,并说明所定义的信号量的含义。要求用伪代码描述。
答:如下述伪代码所示,重要部分注释:
semaphore mutex = 1;//互斥信号量
semaphore even = 0;//缓冲区偶数个数
semaphore odd = 0;//缓冲区奇数个数
semaphore empty = n;//缓冲区空闲个数
// @invariant empty + odd + even = n;
Producer() {
while(1) {
num = produce_an_interger(); //生产一个数据
P(empty); //当buffer有空可以放入数据
P(mutex); //进入临界区
add_num_to_buffer(); //加入生产元素入buffer
if (num % 2 == 0) { //根据生产元素决定唤醒哪个进程
V(even);
} else {
V(odd);
}
V(mutex); //释放资源
}
}
P1() {
while(1) {
P(odd); //接到Produce通知后唤醒P1
P(mutex); //进入临界区
getodd(); //从buffer中获取奇数
V(mutex); //离开临界区
V(empty); //缓冲区元素个数减一
countodd(); //消费数据
}
}
P2() {
while(1) {
P(oven); //接到Produce通知后唤醒P2
P(mutex); //进入临界区
getoven(); //从buffer中获取偶数
V(mutex); //离开临界区
V(empty); //缓冲区元素个数减一
countoven(); //消费数据
}
}
搜索-插入-删除问题
问题:三个线程对一个单链表进行并发的访问,分别进行搜索、插入和删除。搜索线程仅仅读取链表,因此多个搜索线程可以并发。插入线程把数据项插入到链表最后的位置;多个插入线程必须互斥防止同时执行插入操作。但是,一个插入线程可以和多个搜索线程并发执行。最后,删除线程可以从链表中任何一个位置删除数据。一次只能有一个删除线程执行;删除线程之间,删除线程和搜索线程,删除线程和插入线程都不能同时执行。请编写三类线程的同步互斥代码,描述这种三路的分类互斥问题。
答:如下述伪代码所示,重要部分注释:
semaphore mutex_for_serach_number = 1; //查找数量互斥信号量
semaphore mutex_for_insert_number = 1; //插入数量互斥信号量
int serach_number = 0;
int insert_number = 0;
semaphore mutex_for_insert = 1; //多插入操作互斥
semaphora mutex_for_no_serach = 1; //无查询操作
semaphora mutex_for_no_insert = 1; //无插入操作
Inserter() {
P(mutex_for_insert_number);
if (number_insert == 0) {
P(mutex_for_no_insert);
}
number_insert ++;
V(mutex_for_no_insert);
P(mutex_for_insert);//只允许同时有一个插入操作
insert_element();
V(mutex_for_insert);
P(mutex_for_insert_number);
number_insert --;
if (number_insert == 0) {
V(mutex_for_no_insert);
}
V(mutex_for_no_insert);
}
Seracher() {
P(mutex_for_serach_number);
if (number_serach == 0) {
P(mutex_for_no_serach);
}
number_serach ++;
V(mutex_for_serach_number);
serach_for_element();
P(mutex_for_serach_number);
number_serach --;
if (number_serach == 0) {
V(mutex_for_no_serach);
}
V(mutex_for_serach_number);
}
Deletor() {
P(mutex_for_no_insert); //同时拿到无插入和查找通知
P(mutex_for_no_serach);
delete_element();
V(mutex_for_no_insert);
V(mutex_for_no_serach);
}