码迷,mamicode.com
首页 > 其他好文 > 详细

210 - Concurrency Simulator

时间:2016-05-13 00:47:33      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:

Concurrency Simulator

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, &times[0], &times[1], &times[2], &times[3], &times[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;
}

210 - Concurrency Simulator

标签:

原文地址:http://blog.csdn.net/q547550831/article/details/51346205

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!