模擬併發,n個程序切換進行,共享變量。每一個時刻只能有一個程序在運行,每次運行分配了大小爲quantum的時間,在一時間內運行程序中耗時爲t[i]的指令。ios
運行quantum時間後,程序進入[準備隊列]隊尾。指令lock在實際的併發中做用是申請對變量獨佔訪問(本題中只改變程序順序),若是已經有一個程序執行了lock,另外一個程序再次執行lock將會被添加到[阻塞隊列]隊尾,quantum直接結束,不進入[準備隊列]。直到原lock程序執行unlock,[阻塞隊列]隊首程序出隊,進入[等待隊列]隊首。併發
[等待隊列]能夠插入隊首,所以是個[雙端隊列]。每個程序執行到哪條指令能夠用一個指針/索引表示。spa
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<string> 5 #include<queue> 6 #include<deque> 7 #include<cstring> 8 9 using namespace std; 10 11 typedef struct { 12 vector<string> statements; //存放指令語句 13 int eip = 0; //當前指令指針 14 bool pushed = 0; //標誌程序是否入阻塞隊 15 } Program; 16 17 vector<Program> programs; 18 19 int test_cases, n, t[5], q, vars[26]; 20 21 queue<int> blocked_queue; //push pop 22 deque<int> ready_queue; //push_front push_back pop_front pop_back 23 24 bool glock = 0; 25 int pid, time_count; 26 27 void assign_ins() 28 { 29 int &eip = programs[pid].eip; 30 string &ins = programs[pid].statements[eip]; 31 int int_const = stoi(ins.substr(4)); //v = ? 32 vars[ins[0] - 'a'] = int_const; 33 34 eip++; 35 time_count += t[0]; 36 } 37 38 void print_ins() 39 { 40 int &eip = programs[pid].eip; 41 char var = programs[pid].statements[eip][6]; 42 printf("%d: %d\n", pid+1, vars[var - 'a']); 43 44 eip++; 45 time_count += t[1]; 46 } 47 48 bool lock_ins() 49 { 50 //不考慮重複鎖 51 if(glock) //當前已經有鎖 52 { 53 if(!programs[pid].pushed) 54 { 55 blocked_queue.push(pid); 56 programs[pid].pushed = 1; 57 } 58 time_count += q; //鎖住的狀況下,什麼都作不了,直接超時 59 return 0; 60 } 61 else { 62 glock = 1; 63 64 programs[pid].eip++; 65 time_count += t[2]; 66 return 1; 67 } 68 } 69 70 void unlock_ins() 71 { 72 glock = 0; 73 if(!blocked_queue.empty()) 74 { 75 int blocked_id = blocked_queue.front(); blocked_queue.pop(); 76 programs[blocked_id].pushed = 0; //從等待隊列中釋放 77 ready_queue.push_front(blocked_id); 78 } 79 80 programs[pid].eip++; 81 time_count += t[3]; 82 } 83 84 void end_ins() 85 { 86 programs[pid].eip++; //eip == programs[pid].statements.size() 87 time_count += q; 88 } 89 90 91 int main() 92 { 93 scanf("%d", &test_cases); 94 while(test_cases--) 95 { 96 scanf("%d", &n); 97 for(int i = 0; i < 5; i++) 98 scanf("%d", t+i); 99 scanf("%d ", &q); 100 101 memset(vars, 0, sizeof(vars)); 102 programs.clear(); 103 programs.resize(n); 104 105 string str; 106 for(int i = 0; i < n; i++) 107 while(getline(cin, str)) 108 { 109 programs[i].statements.push_back(str); 110 if(str[2] == 'd') 111 break; 112 } 113 114 //程序入隊 115 for(int i = 0; i < n; i++) 116 ready_queue.push_back(i); 117 118 while(!ready_queue.empty()) 119 { 120 pid = ready_queue.front(); ready_queue.pop_front(); 121 time_count = 0; 122 123 bool ready_flag = 1; 124 while(time_count < q) //程序時間內 125 { 126 int &eip = programs[pid].eip; 127 switch(programs[pid].statements[eip][2]) //變量名問題,不能用首字符 128 { 129 case '=': 130 assign_ins(); 131 break; 132 case 'i': 133 print_ins(); 134 break; 135 case 'c': 136 ready_flag = lock_ins(); 137 break; 138 case 'l': 139 unlock_ins(); 140 break; 141 case 'd': 142 end_ins(); 143 ready_flag = 0; 144 break; 145 default: 146 break; 147 } 148 } 149 if(ready_flag) 150 ready_queue.push_back(pid); 151 } 152 if(test_cases > 0) 153 printf("\n"); 154 } 155 return 0; 156 }
寫代碼過程當中的bug總結:指針
1.必定要注意保證循環能夠退出,循環不能正常退出,輸出會混亂(甚至不符合代碼邏輯)。特別注意:*循環條件不是計數,而是隊列爲空之類的判斷,保證隊列必定會運行到爲空。code
2.根據輸入條件選擇對應處理時,要看清楚判斷方式會不會干擾,好比本題中"end"和「e = 1」首字符str[0]都爲'e',因此不能選首字符判斷。blog
3.一些標誌位,好比Program.pushed,置爲1以後要注意有對應的地方將其置爲0。索引
一些擴展的想法:在本題基礎上實現併發控制,給IO操做設置耗時t > quantum,不放入準備隊列。IO完成產生中斷,把它插到準備隊列隊首。lock後,其餘執行修改共享變量的程序進入阻塞隊列,等unlock。以上是瞎想的。隊列