Knižnica pthread
bežne dostupná na unixových systémoch
umožňuje spúšťať a synchronizovať programový kód vo vláknach.
Vlákno je v tejto knižnici reprezentované typom pthread_t
,
každá premenná tohto typu môže reprezentovať jedno vlákno. Na
vytvorenie vlákna a spustenie používateľom definovanej funkcie slúži
funkcia pthread_create.
Funkcia spúšťaná vo vlákne musí mať nasledovný typ:
void* thread_main(void*);
t.j. musí mať jediný parameter - netypový ukazovateľ a návratová hodnota je opäť netypový ukazovateľ. Vďaka tomu môžme vláknu pri spustení dať k dispozícii ľubovoľné dáta na spracovanie a rovnako môže vlákno vyprodukovať vlastné dáta a vrátiť ukazovateľ na ich umiestnenie v pamäti.
![]() |
Dôležité |
---|---|
Tak ako vždy pri práci s ukazovateľmi, musíme dbať na to aby ukazovovateľ ostal platný kým ho používa vlákno alebo jeho volajúci, t.j. ak bol blok pamäti alokovaný dynamicky aby nebol predčasne uvoľnený alebo ak sú dáta umiestnené na zásobníku, aby proces neopustil blok programu, kde boli dáta na zásobník uložené. Na druhej strane musíme pamätať na správne uvoľnenie dynamicky pridelenej pamäti. Ak pamäť pre vstupné dáta vlákna alokovala dynamicky funkcia, ktorá vlákno spúšťa, je potrebné jednoznačne určiť, kto bude zodpovedný za jej uvoľnenie. Podobne, ak vlákno dynamicky alokovalo pamäť pre výstupné údaje, je potrebné aby bola táto pamäť po dokončení vykonávania vlákna uvoľnená. |
V knižnici pthread
môže byť vlákno spustené
v dvoch rôznych režimoch:
pthread_create
vlákno ako joinable.
![]() |
Dôležité |
---|---|
Zjednodušene je možné povedať, že pre každé vlákno spustené
pomocou funkcie |
Cvičenie Vytvorte zdrojový súbor
pthread_fib.c
s nasledovným obsahom:
#include <pthread.h>#include <stdio.h> unsigned dumb_fib(unsigned n)
{ if(n <= 2) return 1; else return dumb_fib(n-1)+dumb_fib(n-2); } struct fib_data
{ unsigned argument; unsigned result; }; void* thread_main(void* pdata)
{ struct fib_data* thread_data = (struct fib_data*)pdata;
thread_data->result = dumb_fib(thread_data->argument);
return NULL;
} int main(void) { struct fib_data thread_data = {45, 0};
pthread_t thread;
pthread_create(&thread, NULL, &thread_main, &thread_data);
pthread_join(thread, NULL);
printf("fib(%u) = %u\n", thread_data.argument, thread_data.result);
return 0; }
Ak chceme používať knižnicu |
|
Veľmi neefektívny spôsob výpočtu Fibonacciho čísel. Používame ho ako príklad jednoduchého algoritmu s veľkou dobou výpočtu. |
|
Štruktúra, ktorú používame na výmenu vstupných a výstupných dát pri výpočte n-tého fibonacciho čísla, medzi hlavným programom a vláknom. |
|
Hlavná funkcia vlákna. |
|
Netypový ukazovateľ |
|
Do premennej |
|
Toto vlákno nepotrebuje vrátiť žiadny iný platný ukazovateľ.
Celá výmena dát prebieha pomocou štruktúry, na ktorú ukazuje
parameter |
|
Vytvoríme a zinicializujeme inštanciu štruktúry |
|
Táto premenná bude reprezentovať bežiace vlákno. |
|
Vytvoríme nové vlákno (identifikované premennou |
|
Keďže vlákno bolo spustené ako joinable,
musíme na jeho dokončenie počkať
pomocou funkcie |
|
Vypíšeme výsledok výpočtu. |
Cvičenie Skopírujte a upravte súbor
Makefile
z predchádzajúceho cvičenia:
OUTPUTS = pthread_fib all: $(OUTPUTS) clean: rm -f $(OUTPUTS) rm -f *.o .PHONY: all clean %: %.c $(CC) -lpthread-o $@ $<
Ak chceme skompilovať program používajúci knižnicu |