第三次作业操作系统补充题答案

第三次作业补充题答案


第五章

1. 桌上有一空盘,最多允许存放一只水果。爸爸可向盘中放一个苹果或放一个桔子,儿子专等吃盘中的桔子,女儿专等吃苹果。

​ 试用semWait、semSignal操作实现爸爸、儿子、女儿三个并发进程的同步。

提示:设置一个信号量表示可否向盘中放水果,一个信号量表示可否取桔子,一个信号量表示可否取苹果。

下面是一个简化版本的C++代码,使用std::mutexstd::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::mutexstd::condition_variable的使用,可以确保爸爸、儿子和女儿的操作是同步的。


**2.**把学生和监考老师都看作进程, 学生有N人, 教师1人. 考场门口每次只能进出一个人, 进考场原则是先来先进. 当N个学生都进入考场后, 教师才能发卷子. 学生交卷后可以离开考场. 教师要等收上来全部卷子并封装卷子后才能离开考场.

(1) 问共需设置几个进程?

(2) 试用信号量操作解决上述问题中的同步和互斥关系.

(1) 共需设置N + 2个进程,其中N个为学生进程,1个为监考老师进程,另外1个用于控制考场门口的进程。

(2) 下面是使用C++和信号量解决上述问题的简化代码。在这个例子中,我们使用std::mutexstd::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::mutexstd::condition_variable来保证学生和老师之间的同步和互斥关系。


第六章

1、a. 3个进程共享4个资源单元,一次只保留或释放一个单元。每个进程最大需要2个单元。说明不会死锁。

b. N个进程共享M个资源单元,一次只能保留或释放一个单元。每个进程最大需要单元数不超过M,并且所有最大需求的总和小于M+N。说明不会发生死锁。

a. 对于这个情况,我们可以使用银行家算法来说明为什么不会发生死锁。银行家算法是一种资源分配和进程调度算法,它通过检查系统的状态来确保在分配资源的情况下不会发生死锁。这个算法基于一个关键的安全性条件,即只有当系统能够找到一个安全序列,才允许分配资源。

在这个具体的例子中,如果每个进程最大需要2个资源单元,而系统总共有4个资源单元,并且每次只分配一个资源单元,那么系统可以在任何时刻满足一个进程的最大需求。即便一个进程同时请求两个资源单元,系统也可以选择只满足其中一个请求,以保持资源的可用性。

b. 对于N个进程共享M个资源单元的情况,每个进程最大需要的单元数不超过M,并且所有最大需求的总和小于M+N,同样可以通过银行家算法来说明不会发生死锁。

如果所有进程的最大需求总和小于M,那么系统始终有足够的资源来满足进程的需求。即使所有进程同时请求资源,系统也可以通过选择适当的进程来分配资源,以确保没有死锁发生。

总之,这两种情况都满足了避免死锁的基本条件,即系统能够找到一个安全序列来满足进程的资源需求。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xwhking

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值