- Modeliuokite mažiausiai trijų tipų resursus.
- Parinkite parametrus, kad aklavietės susidarytų dažnai, bet nebūtinai iš karto.
- Jei aklavietės sėkmingai užkertamos ar šalinamos, programa turėtų veikti amžinai.
- Kokia informacija iš gijų ir kokios galios jas valdyti bus reikalingos jūsų algoritmui?
- Kokia informacija iš gijų ir kokios galios jas valdyti bus reikalingos jūsų algoritmui?
- Atminkite, kad laukimą prie mutekso galima modeliuoti kartojant neblokuojančio užrakto tikrinimą. Čia gija gali, pvz., tikrinti, ar neatėjo žinutė iš pašalinimo algoritmo.
main.cpp yra 4 kodo eilutės, kuriose galima nustatyti pagrindinius kintamuosius:
int mutex_count = 8;
int worker_count = 8;
int lock_after = 10;
int random_after = 10;
- mutex_count nurodo, kiek atskirų resursų bus modeliuojama
- worker_count nurodo, kiek gijų (thread) bus naudojama
- lock_after nurodo, po kiek pagrindinio ciklo iteracijų bus sudaroma aklavietė
- random_after nurodo, po kiek pagrindinio ciklo iteracijų bus naudojamas atsitiktinis resursų rakinimas
Rakinimo seka bus vaizduojama matrica, kurios stulpelių skaičius lygus mutex_count, o eilučių - worker_count. Vienetas reiškia užrakinamą resursą, nulis - nerakinamą:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Tarkime mūsų pradinės sąlygos yra tokios:
int mutex_count = 4;
int worker_count = 4;
int lock_after = 10;
int random_after = 5;
-
Pirmasias 4 iteracijas programa rakins resursus taip, kad visi resursai būtų naudojami tik vienoje gijoje:
1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1
-
Nuo 5 iteracijos programa pradės generuoti atsitiktines matricas, pvz.:
0 1 1 0 1 0 0 0 1 1 0 1 0 1 0 1
-
Pasiekus 10 iteraciją, programa užrakins visus resursus visoms matricoms, garantuodama aklavietę (deadlock):
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Programos metu susidaro situacijos, kada gijai reikia daugiau resursų, nei šiuo metu pasiekiama. Tačiau ji pasiimdama visus, kuriuos gali, tačiau laukdama kitų, gali sudaryti aklavietę. Apsisaugoti nuo tokios situacijos galima naudojant bankininko algoritmą. Jis užtikrina, kad gijos, kurios negali pasiimti visų reikiamų resursų, nesudarys aklavietės.
Tarkime, kad programoje yra 4 modeliuojami duomenys. Programos pradžioje jig visi bus laisvi. Šią informaciją galime atvaizduoti vektoriumi su 4 duomenimis, kurių būsena gali būti 1 arba 0:
1 1 1 1
Paleidus gijas, jos pradeda kreiptis į bankininką, prašydamos užrakinti joms reikalingus duomenis. Šiuos duomenis taip pat galime atvaizduoti vektoriumis su 4 binariais elementais.
Tarkime, kad gija1 kreipiasi į bankininką ir prašo užrakinti pirmąjį resursą, pateikdama prašymą:
1 0 0 0
Bankininkas patikrina, ar reikalingi resursai yra laisvi, lygindamas prašymą su laisvų resursų vektoriumi. Šiuo atveju resursai laisvi, todėl bankininkas užrakina resursą, paleidžia giją ir pasižymi, kad resursas užimtas. Dabar laisvų resursų vektorius atrdodo taip:
0 1 1 1
Atėjus antrai gijai gija2 ir pareikalavus 2 ir 3 resursų:
0 1 1 0
bankininkas juos taip pat užrakina, pasižymi ir paleidžia giją. Dabar laisvų resursų vektorius atrodo taip:
0 0 0 1
Atėjus trečiai gijai gija3 ir pareikalavus duoti resursus:
1 0 0 1
bankininkas aptinka, kad neturi visų reikiamų resursų, kurių reikalauja gija3, todėl gija3 lieka laukti, kol šie resursai atsilaisvins.
Tačiau kai ateina gija4 ir pareikalauja:
0 0 0 1
bankininkas užrakina resursą ir pasižymėjęs, paleidžia giją.
Dabar gija3 turi laukti, kol savo vykdymą pabaigs gija1 ir gija4.
Kiekviena gija prieš kritinės sekcijos pradžią ir jos gale kreipiasi į objekto banker metodus lock(request) ir unlock(request) ir paduoda vektorių true/false verčių, kurios nurodo, kurių resursų gijai reikia. Metodo lock viduje, gija patenka į begalinį ciklą, kuriame laukia, kol bus atlaisvinti visi reikalingi resursai. Tik tada užrakinami gijai reikalingi resursai ir gija gali toliau vykdyti savo darbą.
Programos vykdymo metu, konsolės lange galima stebėti išvedamus duomenis, kurie leidžia įvertinti programos būseną. Išvestis atrodo taip:
------- THREAD 0 -------
Working...
Iteration: 0
Locking at: 16
Random at: 12
------------------------
------- THREAD 0 -------
Working...
Iteration: 1
Locking at: 16
Random at: 12
------------------------
Pirmoje eilutėje nuorodomas gijos skaičius, kurios statusas spausdinamas. Vėliau nurodomas iteracijos skaičius (jis skaičiuojamas bendrai tarp visų gijų). Sekančiose eilutėse spausdinama informacija apie tai, kada bus rakinamos gijos ar generuojamos atsitiktinės rakinimo sąlygos.
Programoje naudomajas mock'inta Banker implementacija, įterpiant failą banker.h. Jūsų banker.h faile turi būti aprašyta klasė Banker su konstruktoriumi, priimančiu modeliuojamų duomenų kiekį mutex_count. Banker klasės objektas turi turėti pasiekiamus metodus .lock(int id), .unlock(int id) ir .cleanup(). Pavyzdys pateiktas banker.h faile.
Irgi rekomenduoju naudoti klasę, kurios objektai turės pasiekiamus metodus. Šiuo metu programoje neturiu implementavęs mock'into jūsų modulio, nes nežinau, kaip veikia jūsų dalies logika. Kai turėsit veikiantį modelį, pranėškit - atnaujinsiu kodą taip, kad irgi užtektų tik įdėti jūsų failą.