Programske paradigme i jezici
Download
1 / 20

Programske paradigme i jezici - PowerPoint PPT Presentation


  • 126 Views
  • Uploaded on

SVEUČILIŠTE U ZAGREBU FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA Zavod za primijenjen o računarstvo. Programske paradigme i jezici. 8. auditorne vježbe (Multithreading). Višenitnost (višedretvenost, eng. multithreading).

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Programske paradigme i jezici' - arvin


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Programske paradigme i jezici

SVEUČILIŠTE U ZAGREBU

FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA

Zavod za primijenjenoračunarstvo

Programske paradigme i jezici

8. auditorne vježbe

(Multithreading)


Vi enitnost vi edretvenost eng multithreading
Višenitnost (višedretvenost, eng. multithreading)

  • Višenitni program sastoji se od 2 ili više dijelova koji se mogu istovremeno izvršavati (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, matrični kalkulator...

  • Prednost: Bolja iskoristivost procesorskog vremena, posebno kod programa koji imaju sporiji I/O.

Progress


Vi enitnost
Višenitnost

  • Razredi koji podržavaju višenitno programiranje nalaze se u prostoru imena System.Threading

  • Kako bi se koristila nit, treba instancirati objekt tipa Thread.

  • Najčešće korišteni konstruktori razreda Thread

    public Thread(ThreadStart start)

    public Thread(ParameterizedThreadStart start)

  • start je ime postupka koja će biti pozvan kako bi počelo izvršavanje niti.

  • ThreadStart je delegat (neprecizno rečeno: pokazivač na postupak)

  • Jednom kreirana nit se pokreće postupkom Start()

    SimpleThread


Vi enitnost simplethread program
Višenitnost (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,

//može nositi bilo koje ime, ne može 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 + " završio");

}

*ParameterizedThreadStart može imati 1 parametar


Vi enitnost simplethread program1
Višenitnost (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");

}

}


Vi enitnost1
Višenitnost

  • Statička metoda Sleep uzrokoje privremeno zaustavljanje izvršavanja niti iz koje je pozvana za navedeni broj milisekundi.

  • Načinimo neke promjene u prethodnom programu

    • Neka se nit pokreće odmah pri instanciranju. Ovo ćemo napraviti instancirajući Thread unutar konstruktora razreda MojThread.

    • Svaki Thread objekt ima svojstvo Name što možemo koristiti umjesto imeThread.

    • Neka glavni program koristi neki drugi način utvrđivanja kraja pokrenutih niti pomoću metode IsAlive

      • public bool IsAlive {get; }

        SimpleThread2


Vi enitnost simplethread2 program
Višenitnost (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 + " završio");

}


Vi enitnost simplethread2 program1
Višenitnost (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

{

Console.Write(".");

Thread.Sleep(100);

}

while (mt1.thread.IsAlive && mt2.thread.IsAlive);

Console.WriteLine("Kraj glavnog threada");

}

}

}

  • Drugi način čekanja na završetak pojedine niti je Join postupak. Najjednostavniji oblik je

    public void Join()

  • Join čeka dok se nit na kojoj je pozvan ne završi. U slučaju da nit nije pokrenuta dogodit će se iznimka: ThreadStateException

mt1.thread.Join();

mt2.thread.Join();

Join uzrokuje blokiranje niti dok nit na koju se čeka ne završi.


Vi enitnost prioriteti
Višenitnost (prioriteti)

  • Postavljanje prioriteta pojedine niti obavlja se preko svojstva Priority koji je član razreda Thread. Njegov opći oblik je public ThreadPriority Priority{ get; set; }

  • ThreadPriorityje pobrojani tip koji definira sljedeće prioritete:

    • ThreadPriority.Highest

    • ThreadPriority.AboveNormal

    • ThreadPriority.Normal (inicijalna vrijednost)

    • ThreadPriority.BelowNormal

    • ThreadPriority.Lowest

  • Sljedeći primjer kreira dvije niti, jednu višeg prioriteta, a drugu nižeg koje završavaju onog trenutka kada brojač u jednoj od njih dođe do 1 000 000 000.

    PriorityDemo


Vi enitnost prioritydemo
Višenitnost (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 + " završio");

}

}


Vi enitnost prioritydemo1
Višenitnost (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);

}

}


Vi enitnost stanja niti
Višenitnost (stanja niti)

  • Stanje niti može se dobiti iz svojstva ThreadState koji se nalazi unutar razreda Thread:

    public ThreadState ThreadState {get; }

  • Stanje može poprimiti jednu od sljedećih vrijednosti:

    ThreadState.Aborted

    ThreadState.AbortRequested

    ThreadState.Background

    ThreadState.Running

    ThreadState.Stopped

    ThreadState.StopRequested

    ThreadState.Suspended

    ThreadState.SuspendRequested

    ThreadState.Unstarted

    ThreadState.WaitSleepJoin

  • Referencu na trenutno nit možemo dobiti pomoću svojstva CurrentThread


Vi enitnost suspend resume abort
Višenitnost (Suspend, Resume, Abort)

  • Thread.Suspend() – privremeno zaustavlja izvršavanje niti

  • Thread.Resume() – ponovo pokreće privremeno zaustavljenu nit

  • Thread.Abort() – uzrokuje ThreadAbortException na niti na kojoj se izvrši, što uzrokuje završetak niti

  • Napomena: Ova iznimka može biti uhvaćena, ali se automatski ponovo generira, osim u slučaju ako se pozove metoda ResetAbort()

  • SuspendResumeAbort


Vi enitnost suspend resume abort1
Višenitnost (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 + " završio");

}


Vi enitnost suspend resume abort2
Višenitnost (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);

mt1.thread.Suspend();

Console.WriteLine("Suspending Thread");

Thread.Sleep(1000);

mt1.thread.Resume();

Console.WriteLine("Resuming Thread");

Thread.Sleep(1000);

Console.WriteLine("Stopping Thread");

mt1.thread.Abort();

mt1.thread.Join();

Console.WriteLine("Kraj glavnog threada");

}

}

Uočimo da nit nije ispisala poruku da se normalno završila (dogodila se neuhvaćena iznimka)

Kao parametar za Abort možemo unijeti bilo koji objekt.Unesimo npr. neki broj

mt1.thread.Abort(100);


Vi enitnost suspend resume abort3
Višenitnost (Suspend, Resume, Abort)

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 + " završio");

}

try{

Uhvatimo ThreadAbortException i ispišemo odgovarajuću poruku

}

catch(ThreadAbortException exc) {

Console.WriteLine("Thread aborted, code: " + exc.ExceptionState);

}

Thread.ResetAbort();

Console.WriteLine("Resetiram abort->nastavljam izvršavanje");

Uočimo poruku


Vi enitnost sinkronizacija
Višenitnost (Sinkronizacija)

  • Promotrimo sljedeći primjer: Neka su startane 3 niti, i neka svaka od njih treba u zajedničku datoteku zapisati nekoliko rečenica, ali pišući znak po znak. Svaka od niti u svom konstruktoru kao parametar će dobiti listu rečenica (ArrayList- varijabla recenice) koje treba zapisati u datoteku i StreamWriter (varijable writer) pomoću kojeg će vršiti upisivanje u datoteku. Kod koji upisuje u datoteku neka je sljedeći:

    foreach(String s in recenice){

    foreach (char c in s){

    Thread.Sleep(10);

    writer.Write(c);

    }

    writer.WriteLine();

    }

  • WriteSentence_NoSync

  • Pokrenemo li gornji program vidjet ćemo da nam je ispis u datoteci izmiješan.

  • Zaštitit ćemo pristup pojedinom dijelu koda, kako bi omogućili da rečenice budu pravilno ispisane.

  • WriteSentence

  • AccountTransaction

lock(writer){

Programski odsječak u kojem se pojedina rečenica zapisuje ogradimo sa lock(writer) i onemogućimo istovremeni ulazak dviju niti u taj odsječak.

}


Vi enitnost sinkronizacija1
Višenitnost (Sinkronizacija)

  • Opći oblik lock naredbe je

    lock(object){

    //programski odsječak koji treba sinkronizirati

    }

  • lock naredba osigurava da dio programa zaštićen lock-om (lock nad nekim objektom) može biti izvršavan samo onom niti koja je vlasnik tog lock-a.

  • Ako neka nit ‘zaključa’ object sve ostale niti koje pokušaju ući u neki programski odsječak koji je zaštićen tim istim objektom moraju čekati dok nit ‘vlasnik’ objekta ne napusti zaštićeni odsječak.

  • lock objekt može biti bilo što (pa i string), ali treba paziti da ne dođe do potpunog zastoja. Najbolje je koristiti privatni objekt namijenjen isključivo za tu svrhu.

  • lock je zapravo jednostavni oblik korištenja sinkronizacijskih postupaka definiranih u razredu Monitor. Definirano je nekoliko postupaka: Enter,Exit,TryEnter,Wait,Pulse,PulseAll


Vi enitnost sinkronizacija2
Višenitnost (Sinkronizacija)

  • Promotrimo sljedeću situaciju: Neka je nit A pozvala postupak T koji je ušao unutar zaštićenog 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 držati vlasništvo nad objektom T, sprečavajući neke druge niti da uđu u odsječke zaštićene tim objektom.

    Rješenje je da A privremeno otpusti vlasništvo nad objektom i omogući nekoj drugoj niti ulazak u kritični odsječak. Kada resurs R postane dostupan, nit A će biti obaviještena i moći će nastaviti svoje izvršavanje uz ponovo zaključavanje objekta.

    Gornje rješenje omogućuju postupci Wait (čekanje određenog objekta) te Pulse (notificiranje o dostupnosti objekta)

  • TickTock

  • Opasnost od potpunog zastoja!


Vi enitnost sinkronizacija3
Višenitnost (Sinkronizacija)

  • Semafori ograničavaju broj niti koje mogu istovremeno pristupiti određenom resursu (kritičnom odsječku)

  • Ukoliko je trenutna vrijednost semafora nula, niti čekaju dok se vrijednost ne poveća. Ovisno o vrijednosti semafora toliki broj niti dobiva pravo izvršavanja kritičnog odsječka. Redoslijed odabranih nije deterministički.

  • Najčešći konstruktor:

    Semaphore(int initialCount, int maximumCount)

  • Najčešći postupci

    WaitOne()

    Release()

  • Progress


ad