Fire de execuție
Un fir de execuție (sau thread în engleză) este definit ca un flux independent de instrucțiuni care pot fi planificate de către sistemul de operare. Din punct de vedere al unui programator, un fir de execuție poate fi descris cel mai bine ca o funcție care rulează independent de programul principal, iar un program paralel (cu mai multe fire de execuție, sau multi-threaded) poate fi privit ca toată mulțimea de astfel de funcții care pot fi planificate să ruleze simultan și/sau independent de către sistemul de operare.
Relația dintre program, proces și thread
Un program reprezintă o colecție de instrucțiuni. Când un program este rulat, acesta poate genera unul sau mai multe procese. Fiecare proces este izolat, ceea ce înseamnă că nu partajează spațiul de adrese cu alte proces, ceea ce înseamnă că fiecare proces deține propria stivă, propriile variabile și date.
În interiorul unui proces, pot exista unul sau mai multe fire de execuție (thread-uri). Spre deosebire de procesele separate, firele de execuție din cadrul aceluiași proces partajează resursele acestuia, cum ar fi memoria, fișierele deschise sau variabilele globale, ceea ce le permite să colaboreze eficient.
În cazul celor mai multe tehnologii de programare paralelă destinate sistemelor MIMD (inclusiv în Pthreads), un thread este definit ca un apel de funcție care se execută independent. Aceste thread-uri au astfel propria stivă și propriul Program Counter, dar funcționează într-un spațiu de memorie comun cu toate thread-urile din același proces.
Astfel, există o distincție foarte importantă între conceptul de proces și cel de thread, pe care este nevoie să o stăpâniți!
Deoarece thread-urile din același proces împart aceleași resurse:
- Modificările făcute de un thread (de exemplu, închiderea unui fișier) sunt vizibile pentru toate celelalte thread-uri din proces;
- Doi pointeri cu aceeași valoare se referă la aceeași zonă de memorie pentru toate firele de execție;
- Citirea și scrierea concurentă în aceeași zonă de memorie este posibilă, dar necesită mecanisme de sincronizare (pe care le veți studia în detaliu în laboratorul 2).
Când are sens folosirea mai multor fire de execuție?
Programele care beneficiază de implementare multi-threaded prezintă, de obicei, una sau mai multe dintre următoarele caracteristici:
- Au componente ce pot rula în paralel;
- Manipulează volume mari de date care se pot procesa în paralel;
- Se blochează frecvent așteptând după operații de I/O (ex. scriere pe disc);
- Trebuie să răspundă rapid la evenimente asincrone (ex. input de la utilizator, notificări externe);
- Au componente cu priorități diferite (ex. un thread responsabil de interfața grafică trebuie să răspundă imediat, în timp ce unul de procesare poate rula în fundal).