标签:
PS:这道题目,看懂题意就费了好大功夫。跟着RuJia的程序走了一遍,调试了一遍才明白个大概,只能说基础不是很好,还需要大量的时间学习。
PS:因为该题排版较麻烦,这里给出OJ网址:UVa210 - Concurrency Simulator
你的任务是模拟n个程序(按输入顺序编号为1~n)的并行执行。每个程序包含不超过25条语句,格式一共有5种:
- var = constant(赋值);
- print var(打印);
- lock;
- unlock;
- end。
变量用单个小写字母表示,初始为0,为所有程序公有(因此在一个程序里对某个变量赋值可能会影响另一个程序)。常数是小于100的非负整数。
每个时刻只能有一个程序处于运行态,其他程序均处于等待态。上述5种语句分别需要t1、t2、t3、t4、t5单位时间。运行态的程序每次最多运行Q个单位时间(称为配额)。当一个程序的配额用完之后,把当前语句(如果存在)执行完之后该程序会被插入一个等待队列中,然后处理器从队首取出一个程序继续执行。初始等待队列包含按输入顺序排列的各个程序,但由于lock/unlock语句的出现,这个顺序可能会改变。
lock的作用是申请对所有变量的独占访问。lock和unlock总是成对出现,并且不会嵌套。lock总是在unlock的前面。当一个程序成功执行完lock指令之后,其他程序一旦试图执行lock指令,就会马上被放到一个所谓的阻止队列的尾部(没有用完的配额就浪费了)。当unlock执行完毕后,阻止队列的第一个程序进入等待队列的首部。
/**
pid:进程编号
id[pid]:该进程执行到的指令位置
prog[id[pid]]:该指令位置对应的指令内容
**/
#include <cstdio>
#include <queue>
#include <cstring>
#include <cctype>
using namespace std;
const int maxNum = 1005;
// n个进程
int n;
// 表示5个指令所花的时间
int times[5];
// 周期时间
int quantum;
// 26个变量
int val[26];
// 指令
char prog[maxNum][10];
// 值为进程运行在指令的位置
int id[maxNum];
// 就绪队列
deque<int> readyQ;
// 阻塞队列
queue<int> blockQ;
// 锁
bool locked;
// 执行指令
void run(int pid) {
// 周期时间
int q = quantum;
while(q > 0) {
// 获取指令
char *p = prog[id[pid]];
switch(p[2]) {
// 举例 a = 22
case ‘=‘ : {
// 常量为正整数,且小于100
val[p[0] - ‘a‘] = isdigit(p[5]) ? (p[4] - ‘0‘) * 10 + (p[5] - ‘0‘) : p[4] - ‘0‘;
q -= times[0];
break;
}
// 举例 print a
case ‘i‘ : {
printf("%d: %d\n", pid + 1, val[p[6] - ‘a‘]);
q -= times[1];
break;
}
// 举例 lock
case ‘c‘ : {
// 已lock,则将进程加入阻塞队列
if(locked) {
blockQ.push(pid);
return;
}
// 上锁
locked = true;
q -= times[2];
break;
}
// 举例 unlock
case ‘l‘ : {
// 解锁
locked = false;
// 当阻塞队列不为空,则将阻塞队列的第一个加入到就绪队列的第一个
if(!blockQ.empty()) {
int pid2 = blockQ.front();
blockQ.pop();
readyQ.push_front(pid2);
}
q -= times[3];
break;
}
// end
case ‘d‘ : {
return;
}
}
// 找到该进程的下一条指令
id[pid]++;
}
// 将该进程加入到执行队列最后
readyQ.push_back(pid);
}
int main() {
// T组用例
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d%d%d%d%d%d\n", &n, ×[0], ×[1], ×[2], ×[3], ×[4], &quantum);
memset(val, 0, sizeof(val));
// 表示第几行指令
int line = 0;
// 为每个进程提供一些指令
for(int i = 0; i < n; i++) {
// 读取一行放入指令数组
fgets(prog[line++], maxNum, stdin);
// 初始化每一个进程在指令数组的开始位置
id[i] = line - 1;
// 指令不为end,再读取一行指令
while(prog[line - 1][2] != ‘d‘) {
fgets(prog[line++], maxNum, stdin);
}
// 放入进程编号
readyQ.push_back(i);
}
// 先置锁为未上锁状态
locked = false;
// 就绪队列不为空
while(!readyQ.empty()) {
// 获取就绪队列最前面的进程编号
int pid = readyQ.front();
readyQ.pop_front();
// 执行指令
run(pid);
}
if(T) {
printf("\n");
}
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/q547550831/article/details/51346205