Professional Documents
Culture Documents
08 Auditorne
08 Auditorne
08 Auditorne
Progress
Vienitnost
Razredi koji podravaju vienitno programiranje nalaze se u prostoru imena System.Threading Kako bi se koristila nit, treba instancirati objekt tipa Thread. Najee koriteni konstruktori razreda Thread public Thread(ThreadStart start) public Thread(ParameterizedThreadStart start) start je ime postupka koja e biti pozvan kako bi poelo izvravanje niti. ThreadStart je delegat (neprecizno reeno: pokaziva na postupak) Jednom kreirana nit se pokree postupkom Start() SimpleThread
3
Vienitnost
Statika metoda Sleep uzrokoje privremeno zaustavljanje izvravanja niti iz koje je pozvana za navedeni broj milisekundi. Nainimo neke promjene u prethodnom programu
Neka se nit pokree odmah pri instanciranju. Ovo emo napraviti instancirajui Thread unutar konstruktora razreda MojThread. Svaki Thread objekt ima svojstvo Name to moemo koristiti umjesto imeThread. Neka glavni program koristi neki drugi nain utvrivanja kraja pokrenutih niti pomou metode IsAlive public bool IsAlive {get; }
SimpleThread2
6
Drugi nain ekanja na zavretak pojedine niti je Join postupak. Najjednostavniji oblik je Join eka dok se nit na kojoj je pozvan ne zavri. U sluaju da nit nije pokrenuta dogodit e se iznimka: ThreadStateException
8
Vienitnost (prioriteti)
Postavljanje prioriteta pojedine niti obavlja se preko svojstva Priority koji je lan razreda Thread. Njegov opi oblik je public
ThreadPriority Priority{ get; set; } ThreadPriority je pobrojani tip koji definira sljedee prioritete: ThreadPriority.Highest ThreadPriority.AboveNormal ThreadPriority.Normal (inicijalna vrijednost) ThreadPriority.BelowNormal ThreadPriority.Lowest
Sljedei primjer kreira dvije niti, jednu vieg prioriteta, a drugu nieg koje zavravaju onog trenutka kada broja u jednoj od njih doe do 1 000 000 000.
PriorityDemo
Vienitnost (PriorityDemo)
using System; using System.Threading; class MojThread{ public int brojac; public Thread thread; static bool stop=false; static string trenutnoIme; public MojThread(string ime){ brojac=0; thread = new Thread(new ThreadStart(this.run)); thread.Name = ime; trenutnoIme = ime; } public void run(){ Console.WriteLine(thread.Name + " startan"); do{ brojac++; if (trenutnoIme!=thread.Name){ trenutnoIme = thread.Name; Console.WriteLine(" Aktivan: " + trenutnoIme); } }while(stop==false && brojac<1000000000); stop = true; Console.WriteLine(thread.Name + " zavrio"); } }
10
Vienitnost (PriorityDemo)
class PriorityDemo { public static void Main() { Console.WriteLine("Glavni thread startan."); //instanciramo MojThread objekte MojThread mt1 = new MojThread("Viseg Prioriteta"); MojThread mt2 = new MojThread("Nizeg Prioriteta"); //postavimo prioritete mt1.thread.Priority = ThreadPriority.AboveNormal; mt2.thread.Priority = ThreadPriority.BelowNormal; //pokrenimo threadove mt1.thread.Start(); mt2.thread.Start(); mt1.thread.Join(); mt2.thread.Join(); Console.WriteLine("Brojac u " + mt1.thread.Name + "je dosao do" + mt1.brojac); Console.WriteLine("Brojac u " + mt2.thread.Name + "je dosao do" + mt2.brojac);
} } 11
13
16
Vienitnost (Sinkronizacija)
Promotrimo sljedei primjer: Neka su startane 3 niti, i neka svaka od njih treba u zajedniku datoteku zapisati nekoliko reenica, ali piui znak po znak. Svaka od niti u svom konstruktoru kao parametar e dobiti listu reenica (ArrayList- varijabla recenice) koje treba zapisati u datoteku i StreamWriter (varijable writer) pomou kojeg e vriti upisivanje u datoteku. Kod koji upisuje u datoteku neka je sljedei:
foreach(String s in recenice){ lock(writer){ foreach (char c in s){ Thread.Sleep(10); writer.Write(c); } writer.WriteLine(); } } Programski odsjeak u kojem se pojedina reenica zapisuje ogradimo sa lock(writer) i onemoguimo istovremeni ulazak dviju niti u taj odsjeak.
WriteSentence_NoSync Pokrenemo li gornji program vidjet emo da nam je ispis u datoteci izmijean. Zatitit emo pristup pojedinom dijelu koda, kako bi omoguili da reenice budu pravilno ispisane. WriteSentence AccountTransaction 17
Vienitnost (Sinkronizacija)
Opi oblik lock naredbe je
lock(object){ //programski odsjeak koji treba sinkronizirati }
lock naredba osigurava da dio programa zatien lock-om (lock nad nekim objektom) moe biti izvravan samo onom niti koja je vlasnik tog lock-a. Ako neka nit zakljua object sve ostale niti koje pokuaju ui u neki programski odsjeak koji je zatien tim istim objektom moraju ekati dok nit vlasnik objekta ne napusti zatieni odsjeak. lock objekt moe biti bilo to (pa i string), ali treba paziti da ne doe do potpunog zastoja. Najbolje je koristiti privatni objekt namijenjen iskljuivo za tu svrhu. lock je zapravo jednostavni oblik koritenja sinkronizacijskih postupaka definiranih u razredu Monitor. Definirano je nekoliko postupaka: Enter,Exit,TryEnter,Wait,Pulse,PulseAll
18
Vienitnost (Sinkronizacija)
Promotrimo sljedeu situaciju: Neka je nit A pozvala postupak T koji je uao unutar zatienog bloka (ili sa lock ili sa Monitor.Enter) i u nekom trenutku treba pristup resursu R koji privremeno nije dostupan. to A treba napraviti? Ako A u nekoj petlji bude ekao na resurs R i dalje e drati vlasnitvo nad objektom T, spreavajui neke druge niti da uu u odsjeke zatiene tim objektom. Rjeenje je da A privremeno otpusti vlasnitvo nad objektom i omogui nekoj drugoj niti ulazak u kritini odsjeak. Kada resurs R postane dostupan, nit A e biti obavijetena i moi e nastaviti svoje izvravanje uz ponovo zakljuavanje objekta. Gornje rjeenje omoguuju postupci Wait (ekanje odreenog objekta) te Pulse (notificiranje o dostupnosti objekta) TickTock Opasnost od potpunog zastoja!
19
Vienitnost (Sinkronizacija)
Semafori ograniavaju broj niti koje mogu istovremeno pristupiti odreenom resursu (kritinom odsjeku) Ukoliko je trenutna vrijednost semafora nula, niti ekaju dok se vrijednost ne povea. Ovisno o vrijednosti semafora toliki broj niti dobiva pravo izvravanja kritinog odsjeka. Redoslijed odabranih nije deterministiki. Najei konstruktor:
Semaphore(int initialCount, int maximumCount)
Najei postupci
WaitOne() Release()
Progress
20