Sunteți pe pagina 1din 10

Ministerul Educaţiei al Republicii Moldova

Universitatea Tehnică a Moldovei


Catedra Automatică și Tehnologii Informaționale

RAPORT

Lucrare de laborator Nr.2


la disciplina Programarea în Rețea
Tema: Programarea multi-threading

A efectuat: st. grupei SI-131, Gheorghisenco L.

A verificat: Antohi Ionel

Chișinău 2016
De ce utilizăm Multi-threading
-O interacțiune mai bună și eficientă cu utilizatorul. Dacă vom avea un singur fir disponibil,
programul va putea realiza doar un singur lucru într-o anumită perioadă de timp. În caz contrariu, avînd
mai multe fire la dispoziție, putem redacta un fișier text în timp ce are loc difuzarea unei melodii și
instalarea unui oarecare soft, ceea ce ne sporește mult randamentul.

-Simularea activităților concomitente. O posibilitate de a afișa mai multe taskuri ca și cum ar


rula simultan, cînd, de fapt, fiecare se execută aparte pentru o scurtă perioadă de timp (are loc
comutarea firelor următoare).

-Exploatarea mai mulor procesoare. Această activitate ne permite să ajungem la o performanță


mult mai înaltă fiind, însăși, o revoluție în domeniul sistemelor de operare.

-Simplifică modelare obiectelor în OOP. Analiza obiect-orientată a sistemului înainte de a fi


inițiat procesul de implementare poate duce la necesitatea, ca unele obiecte să aibă un fir care rulează în
interior. Astfel, un obiect activ poate să-ți schimbe starea autonom (4).
Sarcina propriu-zisă

CountDownE
vent1

CountDown
Event2

Fig.1- Reprezentarea arborelui conform variantei propuse(1).

Observăm următoarele dependențe: 15; 25,6; 35,6; 46 .

Vom utiliza primitiva de sincronizare CountDown, datorită costului (în timp) foarte mic circa
40ns (pentru că nu se introduce/retrage din context). La fel și structura arborelui dat, care ne permite
separarea în două „blocuri” relaționate prin dependențele menționate anterior.

Pentru realizarea sarcinii - sincronizarea propriu-zisă a acestor fire, am utilizat semaforul, un


mecanism (număr natural) asupra căruia se pot executa operațiile atomare (p și v, dacă e să
generalizăm), astfel pentru blocarea firului apelăm Wait(), iar pentru comutare și execuție Signal().
Funcționalitatea pentru CountdownEvent1:
static CountdownEvent cde1 = new CountdownEvent(3);

cde1.Signal(); 1

5 cde1.Wait();
cde1.Signal();
2

3
cde1.Signal();

La orice rulare a codului, firul 5 va aștepta cu amabilitate execuția celorlalte 3, intrînd în anume
acea secțiune critică, oferindu-le posibilitatea celorlate să acționeze.(Vezi fig.2,3)
Execuția programului

Fig.2 – Afișarea ordinii execuției fiecărui fir

Fig.3 – Afișearea ordinii execuției (după zeci de rulări)


În cazul utilizării tehnicii ManualResetEvent, pentru sarcina dată se va utiliza relativ mai mult cod, deci
și resursele vor crește, datorită faptului că vom fi nevoiți manual să gestionăm cu resursa critică, în caz contrariu
ordinea va fi incorectă. (Vezi fig.4)

Fig.4 – Reprezentarea tehnicii de sicronizare ManualResetEvent

Fig.5- Implementarea sarcinii cu ajutorul metodei ManualResetEvent

Concluzie
Efectuînd acest mic studiu, putem spune cu exactitate că multi-threading-ul este un instrument
revoluționar, dar și complex anume pentru că trebuie să ținem cont atît de sarcina propusă, organizarea
coerentă a execuției activităților pe fire, cît și numărul acestora. Pentru a nu avea situații problematice,
greu de identificat (cum ar fi Livelock) sau pierderi de memorie (Memory leak), e nevoie să știm exact
a coordona cu tehnicile propuse în dependență de obiectivul stabilit.
Apariția nedeterminismului datorită cuantelor de timp nealocate este probabil, cea mai întînlnită
situație de conflict și dificultatea nu e în multi-threading, dar anume în cei care îl utilizează.
Dacă e să analizăm structurile de sincronizare, atunci trebuie să luăm în considerație faptul că în
barieră, toate firele se așteaptă una pe lata (trebuie să știu numărul de participanți), dar în semnalizare
putem avea trei fire la intrare și doar unul singur la ieșire, la fel și varibilele partajate pot crea
incertitudini și conflicte.
Bibliografie

1. Dumitru, Ciorbă. Note de laborator. Moodle. [Online] March 9, 2016.


http://moodle.ati.utm.md/mod/book/view.php?id=1855.
2. Albahari, Joseph. Threading in C#. wwww.albahari.com. [Online]
http://www.albahari.com/threading/.
3. MSDN. Coordination Data Structures. www.blogs.msdn.com. [Online]
http://blogs.msdn.com/b/pfxteam/archive/2008/06/18/8620615.aspx.
4. Oracle. Essential Classes . www.docs.oracle.com. [Online]
http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html.
5. Dumitru, Ciorbă. Bursting bubble-threading. www.ciorba.name. [Online] http://ciorba.name/?
p=1308.
6. Inc, Stack Exange. When should you use multithreading. www.stackoverflow.com. [Online]
http://stackoverflow.com/questions/7419619/when-should-you-use-multithreading-and-would-multi-
threading-be-beneficial-if-t.
Anexă

//CountDownEvent

using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

class Program
{
static CountdownEvent cde1 = new CountdownEvent(3);
static CountdownEvent cde2 = new CountdownEvent(3);

static void Main()


{
new Thread(Show_Thread1).Start("Thread 1");
new Thread(Show_Thread2).Start("Thread 2");
new Thread(Show_Thread3).Start("Thread 3");
new Thread(Show_Thread4).Start("Thread 4");
new Thread(Show_Thread5).Start("Thread 5");
new Thread(Show_Thread5).Start("Thread 6");

Console.ReadKey();
}

static void Show_Thread1(Object obj)


{
Console.WriteLine(obj);
cde1.Signal();
}

static void Show_Thread2(Object obj)


{

Console.WriteLine(obj);
cde1.Signal();
cde2.Signal();
}

static void Show_Thread3(Object obj)


{

Console.WriteLine(obj);
cde1.Signal();
cde2.Signal();
}

static void Show_Thread4(Object obj)


{

Console.WriteLine(obj);
cde2.Signal();
}

static void Show_Thread5(Object obj)


{
cde1.Wait();

Console.WriteLine(obj);

static void Show_Thread6(Object obj)


{
cde2.Wait();
Console.WriteLine(obj);

}
}

//ManualResetEvent

using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

class Program
{
//static AutoResetEvent cde1 = new AutoResetEvent(false);
//static AutoResetEvent cde2 = new AutoResetEvent(false);
//static AutoResetEvent cde3 = new AutoResetEvent(true);
// static CountdownEvent cde2 = new CountdownEvent(3);

static ManualResetEvent cde1 = new ManualResetEvent(false);

static ManualResetEvent cde2 = new ManualResetEvent(false);


static ManualResetEvent cde3 = new ManualResetEvent(false);

static ManualResetEvent cde4 = new ManualResetEvent(false);


static void Main()
{
new Thread(Show_Thread1).Start("Thread 1");
new Thread(Show_Thread2).Start("Thread 2");
new Thread(Show_Thread3).Start("Thread 3");
new Thread(Show_Thread4).Start("Thread 4");
new Thread(Show_Thread5).Start("Thread 5");
new Thread(Show_Thread5).Start("Thread 6");
// Console.ReadKey();

Console.Read();
}

static void Show_Thread1(Object obj)


{
Console.WriteLine(obj);
cde1.Set();
}

static void Show_Thread2(Object obj)


{

Console.WriteLine(obj);
cde2.Set();

}
static void Show_Thread3(Object obj)
{

Console.WriteLine(obj);
cde3.Set();
}

static void Show_Thread4(Object obj)


{

Console.WriteLine(obj);
cde4.Set();
}

static void Show_Thread5(Object obj)

{
cde1.WaitOne();
cde2.WaitOne();
cde3.WaitOne();

Console.WriteLine(obj);

static void Show_Thread6(Object obj)


{

cde2.WaitOne();
cde3.WaitOne();
cde4.WaitOne();

Console.WriteLine(obj);