作业操作系统补充题答案"/>
第三次作业操作系统补充题答案
第三次作业补充题答案
第五章
1. 桌上有一空盘,最多允许存放一只水果。爸爸可向盘中放一个苹果或放一个桔子,儿子专等吃盘中的桔子,女儿专等吃苹果。
试用semWait、semSignal操作实现爸爸、儿子、女儿三个并发进程的同步。
提示:设置一个信号量表示可否向盘中放水果,一个信号量表示可否取桔子,一个信号量表示可否取苹果。
下面是一个简化版本的C++代码,使用std::mutex
和std::condition_variable
进行同步操作,以满足爸爸、儿子、女儿三个并发进程的需求。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
char fruit;void father() {while (true) {std::unique_lock<std::mutex> lock(mtx);// 随机选择放入桔子或苹果fruit = (rand() % 2 == 0) ? 'O' : 'A';std::cout << "爸爸放入了一个" << ((fruit == 'O') ? "桔子" : "苹果") << std::endl;// 通知儿子或女儿可以取水果了cv.notify_all();// 等待儿子或女儿吃完cv.wait(lock);}
}void child(const std::string& name, char targetFruit) {while (true) {std::unique_lock<std::mutex> lock(mtx);// 等待可以取对应水果的通知cv.wait(lock, [&] { return fruit == targetFruit; });// 取出水果std::cout << name << "吃了一个" << ((fruit == 'O') ? "桔子" : "苹果") << std::endl;// 通知爸爸可以放入水果了cv.notify_all();}
}int main() {std::thread fatherThread(father);std::thread sonThread(child, "儿子", 'O');std::thread daughterThread(child, "女儿", 'A');fatherThread.join();sonThread.join();daughterThread.join();return 0;
}
这个代码中,爸爸线程不断地往盘中放水果,而儿子和女儿线程则根据自己的口味不断地从盘中取水果吃。通过std::mutex
和std::condition_variable
的使用,可以确保爸爸、儿子和女儿的操作是同步的。
**2.**把学生和监考老师都看作进程, 学生有N人, 教师1人. 考场门口每次只能进出一个人, 进考场原则是先来先进. 当N个学生都进入考场后, 教师才能发卷子. 学生交卷后可以离开考场. 教师要等收上来全部卷子并封装卷子后才能离开考场.
(1) 问共需设置几个进程?
(2) 试用信号量操作解决上述问题中的同步和互斥关系.
(1) 共需设置N + 2个进程,其中N个为学生进程,1个为监考老师进程,另外1个用于控制考场门口的进程。
(2) 下面是使用C++和信号量解决上述问题的简化代码。在这个例子中,我们使用std::mutex
和std::condition_variable
来实现信号量的功能。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>const int N = 5; // 假设有5个学生std::mutex mtx;
std::condition_variable cv;
int studentsInside = 0;
bool teacherInside = false;void student(int id) {std::unique_lock<std::mutex> lock(mtx);// 学生进入考场studentsInside++;// 学生等待发卷cv.wait(lock, [&] { return studentsInside == N && !teacherInside; });std::cout << "学生 " << id << " 收到试卷" << std::endl;// 学生考试完成,离开考场studentsInside--;// 如果是最后一个学生离开,则通知老师可以离开if (studentsInside == 0) {cv.notify_one();}
}void teacher() {std::unique_lock<std::mutex> lock(mtx);// 老师等待所有学生进入考场cv.wait(lock, [&] { return studentsInside == N; });// 发卷子std::cout << "监考老师发卷子" << std::endl;// 学生们考试中,等待收卷cv.wait(lock, [&] { return studentsInside == 0; });// 收卷并封装卷子std::cout << "监考老师收卷并封装卷子" << std::endl;// 通知所有学生可以离开cv.notify_all();
}int main() {std::thread teacherThread(teacher);std::thread studentsThreads[N];for (int i = 0; i < N; ++i) {studentsThreads[i] = std::thread(student, i);}for (int i = 0; i < N; ++i) {studentsThreads[i].join();}teacherThread.join();return 0;
}
这个简化的例子中,每个学生线程表示一个学生,老师线程表示监考老师。使用std::mutex
和std::condition_variable
来保证学生和老师之间的同步和互斥关系。
第六章
1、a. 3个进程共享4个资源单元,一次只保留或释放一个单元。每个进程最大需要2个单元。说明不会死锁。
b. N个进程共享M个资源单元,一次只能保留或释放一个单元。每个进程最大需要单元数不超过M,并且所有最大需求的总和小于M+N。说明不会发生死锁。
a. 对于这个情况,我们可以使用银行家算法来说明为什么不会发生死锁。银行家算法是一种资源分配和进程调度算法,它通过检查系统的状态来确保在分配资源的情况下不会发生死锁。这个算法基于一个关键的安全性条件,即只有当系统能够找到一个安全序列,才允许分配资源。
在这个具体的例子中,如果每个进程最大需要2个资源单元,而系统总共有4个资源单元,并且每次只分配一个资源单元,那么系统可以在任何时刻满足一个进程的最大需求。即便一个进程同时请求两个资源单元,系统也可以选择只满足其中一个请求,以保持资源的可用性。
b. 对于N个进程共享M个资源单元的情况,每个进程最大需要的单元数不超过M,并且所有最大需求的总和小于M+N,同样可以通过银行家算法来说明不会发生死锁。
如果所有进程的最大需求总和小于M,那么系统始终有足够的资源来满足进程的需求。即使所有进程同时请求资源,系统也可以通过选择适当的进程来分配资源,以确保没有死锁发生。
总之,这两种情况都满足了避免死锁的基本条件,即系统能够找到一个安全序列来满足进程的资源需求。
更多推荐
第三次作业操作系统补充题答案
发布评论