题目
有一个盘子,可以放5个水果(苹果or桔子)。
父亲每次向盘子随机放入一个水果(苹果or桔子),父亲放入水果的次数不少于11次。
儿子只吃桔子,女儿只吃苹果。
请编程使用信号量机制模拟解决此进程同步问题。
打印信息包括盘子的情况、调度的情况以及父亲、儿子或者女儿执行的操作。
代码
//
// Created by Jintao on 2019/12/15.
//
// 题目:
// 有一个盘子,可以放5个水果(苹果or桔子)。
// 父亲每次向盘子随机放入一个水果(苹果or桔子),父亲放入水果的次数不少于11次。
// 儿子只吃桔子,女儿只吃苹果。
// 请编程使用信号量机制模拟解决此进程同步问题。
// 打印信息包括盘子的情况、调度的情况以及父亲、儿子或者女儿执行的操作。
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cstring>
#include<array>
#include<list>
/// 进程是哪一个
enum struct PType {
father, son, dau
};
/// 水果类型枚举
enum struct Fruit {
empty, orange, apple
};
/// 进程的数组, N代表数组容量大小, length代表进程个数(数组长度)
template<unsigned int N>
struct ProcArray {
std::array<PType, N> names;
ProcArray() {}
/// 随机选取一个进程运行。其中 father被调度的概率是 son和dau的2倍
PType randProc() {
int choice = rand() % (N + 1) % N;
return names[choice];
}
};
/// 信号量
struct Semaphore {
int value;
std::list<PType> list;
Semaphore() : value(0) {}
Semaphore(int value) : value(value) {}
/// 如果value>0 则运行,否则阻塞;value--;
/// \return 阻塞: true, 不阻塞: false;
bool P(PType pType);
/// 如果value>=0 则运行,否则唤醒队列首;value--;
void V();
};
/// 餐盘
template<unsigned int N>
struct Dish {
std::list<Fruit> fruList;
int emptyNum = N;
/// 放水果 true: 成功; false: 失败
void putFruit(Fruit fruit);
/// 拿水果 true: 成功; false: 失败
void removeFruit(Fruit fruit);
void printDish();
};
void fatherRun();
void sonRun();
void dauRun();
void run(PType pType);
Semaphore empty(5), orange, apple; // 3个信号量
Dish<5> dish; // 容量为5的盘子
ProcArray<3> procArr; // 3个进程
int runTime = 11; // 运行11次 剩余运行次数
int main() {
srand(time(nullptr));
procArr.names = {PType::father, PType::son, PType::dau};
while (runTime--) {
run(procArr.randProc());
}
printf("\nSemaphore: \n");
printf("empty: %d\n", empty.value);
printf("orange: %d\n", orange.value); // son
printf("apple: %d\n", apple.value); // dau
}
void run(PType pType) {
printf("Before Running - ");
dish.printDish();
switch (pType) {
case PType::father:
printf("Running: Father\n");
if (empty.P(PType::father)) {
return;
}
fatherRun();
break;
case PType::son:
printf("Running: Son\n");
if (orange.P(PType::son)) {
return;
}
sonRun();
break;
case PType::dau:
printf("Running: Daughter\n");
if (apple.P(PType::dau)) {
return;
}
dauRun();
break;
}
printf("After Running - ");
dish.printDish();
printf("\n");
}
void fatherRun() {
switch (rand() % 2) {
case 0: // Fruit::orange
// printInfo
printf("Put a orange on dish\n");
dish.putFruit(Fruit::orange);
orange.V();
break;
case 1: // Fruit::apple
// printInfo
printf("Put a apple on dish\n");
dish.putFruit(Fruit::apple);
apple.V();
break;
}
}
void sonRun() {
// printInfo
printf("Remove a orange from dish\n");
dish.removeFruit(Fruit::orange);
empty.V();
}
void dauRun() {
// printInfo
printf("Remove a apple from dish\n");
dish.removeFruit(Fruit::apple);
empty.V();
}
bool Semaphore::P(PType pType) {
bool block = false; // 阻塞
value--;
if (value < 0) {
block = true;
list.push_back(pType);
printf("Block\n\n");
}
return block;
}
void Semaphore::V() {
PType pType;
value++;
if (value <= 0) {
printf("After Running - ");
dish.printDish();
pType = list.front();
list.pop_front();
switch (pType) {
case PType::son:
printf("\nAwake: Son\n");
sonRun();
break;
case PType::dau:
printf("\nAwake: Daughter\n");
dauRun();
break;
default:
break;
}
}
}
char *__fruitToStr(char *dest, Fruit fruit) {
switch (fruit) {
case Fruit::empty:
strcpy(dest, "empty");
break;
case Fruit::orange:
strcpy(dest, "orange");
break;
case Fruit::apple:
strcpy(dest, "apple");
break;
}
return dest;
}
template<unsigned int N>
void Dish<N>::putFruit(Fruit fruit) {
if (!emptyNum)
abort();
else {
fruList.push_back(fruit);
emptyNum--;
return;
}
}
template<unsigned int N>
void Dish<N>::removeFruit(Fruit fruit) {
for (auto it = fruList.begin(); it != fruList.end(); ++it) {
if (*it == fruit) {
fruList.erase(it);
emptyNum++;
return;
}
}
abort();
}
template<unsigned int N>
void Dish<N>::printDish() {
char fruitTemp[10];
printf("Dish: ");
if (emptyNum == N) {
printf("none\n");
return;
}
for (auto it = fruList.begin(); it != --fruList.end(); ++it) {
printf("%s, ", __fruitToStr(fruitTemp, *it));
}
printf("%s\n", __fruitToStr(fruitTemp, fruList.back()));
}
运行结果
这里就不截图了…
运行结果:
"D:\programming\C C++\OSHomework\cmake-build-debug\homework.exe"
Before Running - Dish: none
Running: Son
Block
Before Running - Dish: none
Running: Daughter
Block
Before Running - Dish: none
Running: Daughter
Block
Before Running - Dish: none
Running: Daughter
Block
Before Running - Dish: none
Running: Father
Put a apple on dish
After Running - Dish: apple
Awake: Daughter
Remove a apple from dish
After Running - Dish: none
Before Running - Dish: none
Running: Father
Put a apple on dish
After Running - Dish: apple
Awake: Daughter
Remove a apple from dish
After Running - Dish: none
Before Running - Dish: none
Running: Father
Put a orange on dish
After Running - Dish: orange
Awake: Son
Remove a orange from dish
After Running - Dish: none
Before Running - Dish: none
Running: Daughter
Block
Before Running - Dish: none
Running: Father
Put a orange on dish
After Running - Dish: orange
Before Running - Dish: orange
Running: Father
Put a orange on dish
After Running - Dish: orange, orange
Before Running - Dish: orange, orange
Running: Father
Put a orange on dish
After Running - Dish: orange, orange, orange
Semaphore:
empty: 2
orange: 3
apple: -2
进程已结束,退出代码 0
同系列
2、操作系统 程序设计作业2——进程调度 (C++实现)
https://blog.csdn.net/qq_40939814/article/details/103548436
3、操作系统 程序设计作业3——进程同步(信号量机制) (C++伪代码实现)
https://blog.csdn.net/qq_40939814/article/details/103548527
5、操作系统 程序设计作业5——模拟分页系统的地址变换(公式法和硬拼法) (C++实现)
https://blog.csdn.net/qq_40939814/article/details/103548645
版权声明:本文为qq_40939814原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。