08 Auditorne

You might also like

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 20

SVEUILITE U ZAGREBU FAKULTET ELEKTROTEHNIKE I RAUNARSTVA Zavod za primijenjeno raunarstvo

8. auditorne vjebe (Multithreading)

Programske paradigme i jezici

Vienitnost (viedretvenost, eng. multithreading)


Vienitni program sastoji se od 2 ili vie dijelova koji se mogu istovremeno izvravati (pseudo-paralelizam). Svaki dio takvog programa naziva se nit ili dretva (eng. thread). Ime dolazi od thread of execution. Svaki proces ima barem jednu nit. Primjer: tekst procesor, web server, matrini kalkulator... Prednost: Bolja iskoristivost procesorskog vremena, posebno kod programa koji imaju sporiji I/O.

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 (SimpleThread program)


using System; using System.Threading; class MojThread{ public int brojac; string imeThreada; public MojThread(string ime){ brojac=0; imeThreada = ime; } //entryPoint , tj. postupak s kojim e se startati thread, //moe nositi bilo koje ime, ne moe primiti nijedan parametar* public void run(){ Console.WriteLine(imeThreada + " startan"); do { Thread.Sleep(500); Console.WriteLine("\nUnutar " + imeThreada + ", brojac=" + brojac); brojac++; } while(brojac<5); Console.WriteLine(imeThreada + " zavrio"); } *ParameterizedThreadStart moe imati 1 parametar

Vienitnost (SimpleThread program)


class Glavni { public static void Main() { Console.WriteLine("Glavni thread startan."); //instanciramo MojThread objekte MojThread mt1 = new MojThread("PPJ-#1"); MojThread mt2 = new MojThread("PPJ-#2"); //konstruiramo Thread objekte Thread thread1 = new Thread(new ThreadStart(mt1.run)); Thread thread2 = new Thread(new ThreadStart(mt2.run)); //startamo threadove thread1.Start();thread2.Start(); do { Console.Write("."); Thread.Sleep(100); } while (mt1.brojac<5 && mt2.brojac<5); Console.WriteLine("Kraj glavnog threada"); } }
5

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

Vienitnost (SimpleThread2 program)


using System; using System.Threading; class MojThread{ public int brojac; public Thread thread; public MojThread(string ime) { brojac=0; thread = new Thread(new ThreadStart(this.run)); thread.Name = ime; thread.Start(); } public void run(){ Console.WriteLine(thread.Name + " startan"); do { Thread.Sleep(500); Console.WriteLine("\nUnutar " + thread.Name + ", brojac=" + brojac); brojac++; } while(brojac<5); Console.WriteLine(thread.Name + " zavrio"); }

Vienitnost (SimpleThread2 program)


class Glavni { public static void Main() { Console.WriteLine("Glavni thread startan."); //instanciramo MojThread objekte MojThread mt1 = new MojThread("PPJ-#1"); MojThread mt2 = new MojThread("PPJ-#2"); do mt1.thread.Join(); { mt2.thread.Join(); Console.Write("."); Thread.Sleep(100); Join uzrokuje blokiranje niti dok nit na koju se eka ne zavri. } while (mt1.thread.IsAlive && mt2.thread.IsAlive); Console.WriteLine("Kraj glavnog threada"); } } }

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

public void Join()

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

Vienitnost (stanja niti)


Stanje niti moe se dobiti iz svojstva ThreadState koji se nalazi unutar razreda Thread: Stanje moe poprimiti jednu od sljedeih vrijednosti:
ThreadState.Aborted ThreadState.AbortRequested ThreadState.Background ThreadState.Running ThreadState.Stopped ThreadState.StopRequested ThreadState.Suspended ThreadState.SuspendRequested ThreadState.Unstarted ThreadState.WaitSleepJoin public ThreadState ThreadState {get; }

Referencu na trenutno nit moemo dobiti pomou svojstva CurrentThread


12

Vienitnost (Suspend, Resume, Abort)


Thread.Suspend() privremeno zaustavlja izvravanje niti Thread.Resume() ponovo pokree privremeno zaustavljenu nit Thread.Abort() uzrokuje ThreadAbortException na niti na kojoj se izvri, to uzrokuje zavretak niti Napomena: Ova iznimka moe biti uhvaena, ali se automatski ponovo generira, osim u sluaju ako se pozove metoda ResetAbort() SuspendResumeAbort

13

Vienitnost (Suspend, Resume, Abort)


using System; using System.Threading; class MojThread{ public Thread thread; public MojThread(string ime){ thread = new Thread(new ThreadStart(this.run)); thread.Name = ime; thread.Start(); } public void run(){ Console.WriteLine(thread.Name + " startan"); for (int i=1; i<=200 ; i++){ Console.Write(i + " "); if ((i%10)==0){ Console.WriteLine(); Thread.Sleep(250); } } Console.WriteLine(thread.Name + " zavrio"); }
14

Vienitnost (Suspend, Resume, Abort)


class SuspendResumeAbort{ public static void Main(){ MojThread mt1 = new MojThread("Moj Thread"); Thread.Sleep(1000); mt1.thread.Suspend(); Console.WriteLine("Suspending Thread"); Thread.Sleep(1000); mt1.thread.Resume(); Console.WriteLine("Resuming Thread"); Thread.Sleep(1000); Uoimo da nit nije ispisala poruku da se normalno mt1.thread.Suspend(); zavrila (dogodila se Console.WriteLine("Suspending Thread"); neuhvaena iznimka) Thread.Sleep(1000); mt1.thread.Resume(); Kao parametar za Abort moemo Console.WriteLine("Resuming Thread"); koji unijeti bilo Thread.Sleep(1000); objekt.Unesimo npr. neki broj Console.WriteLine("Stopping Thread"); mt1.thread.Abort(100); mt1.thread.Abort(); mt1.thread.Join(); Console.WriteLine("Kraj glavnog threada"); } }
15

Vienitnost (Suspend, Resume, Abort)


public void run(){ Console.WriteLine(thread.Name + " startan"); for (int i=1; i<=200 ; i++){ try{ Console.Write(i + " "); if ((i%10)==0){ Uhvatimo ThreadAbortException Console.WriteLine(); i ispiemo odgovarajuu Thread.Sleep(250); poruku } } catch(ThreadAbortException exc) { Thread.ResetAbort(); Console.WriteLine("Thread aborted, code: " + Console.WriteLine("Resetiram abort->nastavljam izvravanje"); exc.ExceptionState); Uoimo poruku } } Console.WriteLine(thread.Name + " zavrio"); }

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

You might also like