Przejdź do treści
Programowanie

Jak dodać wątki do aplikacji (pthreads)?

Mateusz Mierzwiński
Mateusz Mierzwiński Adept
03 maja 2010 ~4 min czytania
Jak dodać wątki do aplikacji (pthreads)?
W niektórych przypadkach gdy nasze programy przetwarzają duże ilości danych sekwencyjnie warto jest zastosować dodatkowe zabiegi zwiększające szybkość działania algorytmu przetwarzania. W pewnych miejscach gdzie funkcje mogą być duplikowane warto zastosować przetwarzanie równoległe. Jednym z mechanizmów przetwarzania równoległego są wątki - POSIX Threads/pthreads. Jest to o wiele korzystniejszy sposób zwielokrotnienia równoległego wykonywania funkcji od wzbudzania w systemie nowego procesu (fork) ponieważ wykorzystuje znacznie mniej zasobów systemowych do pracy - program ładowany jest raz do pamięci i wykonywany równolegle w tylko konkretnych obszarach. Jak więc zastosować wątki? To proste...

Kroki

1
Na samym początku programu dodajemy deklaracje potrzebnych nagłówków - załączamy je tagiem #include. Nas interesuje głównie moduł wątków, zatem dodajemy nagłówek "pthread.h".

#include < pthread.h >
Krok 1
2
Następnie deklarujemy wskaźnik do funkcji, którą zechcemy zwielokrotnić poprzez wykonanie wątkami. Nazwijmy ją "FunkcjaC".

FunkcjaC nie przyjmuej parametrów i zwraca VOID, zatem deklaracja będzie wyglądać następująco:

void *funkcjaC(
Krok 2
3
Do funkcji, która będzie wywoływać wątki (np. blok main()) dodajemy zmienne typu INT, w których przekażemy wskaźniki do wątków lub ewentualne kody błędu:

int w1, w2;
Krok 3
4
W tym miejscu musimy zadeklarować zmienne wątków, które będziemy używać później - cały czas znajdujemy się w bloku funkcji, która utworzy wątki i je zainicjuje. Typ zmiennej to pthread_t.

pthread_t watek1, watek2;
Krok 4
5
Stworzymy teraz warunek (IF), który sprawdzi, czy wątek został utworzony, jednocześnie inicjując wątek. Wykorzystujemy zmienne w1 i w2, watek1, watek2 oraz funkcje pthread_create.

if (w1=pthread_create( &watek1, , &funkcjaC, ))
{
printf("Nie udalo sie utworzyc watku: %d
", w1
}

W ten sposób utworzymy pierwszy wątek, bądź uzyskamy kod błędu w przypadku niepowodzenia tej operacji. Warto jest zauważyć, że wykorzystujemy mechanizm przekazania adresu do funkcji i zmiennej wątku, a nie same zmienne oraz nazwę funkcji.
Krok 5
6
Tworzymy drugi wątek analogicznie do pierwszego:

if (w2=pthread_create( &watek2, , &functionC, ))
{
printf("Nie udalo sie utworzyc watku: %d
", w2
}

Utworzyliśmy drugi wątek - teraz funkcja "funkcjaC" będzie wykonywana równolegle.
Krok 6
7
W większości przypadków warto jest zsynchronizować wątki w głównej mierze po to, aby w przypadku gdy jeden wątek się zakończy a drugi jeszcze ciągle jest w toku program nie przeszedł do dalszego wykonywania instrukcji. W tym celu wykorzystujemy funkcję pthread_join().

Funkcja pthread_join przyjmuje jako 1 parametr nazwę zmiennej (nie jej wskaźnik), zatem synchronizacja wątków będzie wyglądała następująco:

pthread_join( watek1,
pthread_join( watek2,
Krok 7
8
Po wykonaniu kroku 7 wątki ulegną synchronizacji (w określonej kolejności - najpierw wątek1, następnie wątek2). Po wykonaniu tych instrukcji program przejdzie do dalszego wykonywania programu. W celach testowych warto jest zastosować tutaj wyjście z programu w formie funkcji systemowej exit() zwracając 0 jako kod błędu - program wykonany prawidłowo.

Zapisujemy plik, sprawdzamy czy nie popełniliśmy jakichś literówek, dopisujemy wnętrze funkcji "funkcjaC" i możemy przystąpić do...
Krok 8
9
...kompilacji. My w tym celu wykorzystamy kompilator GNU Compiler Collection - GCC. Aby uniknąć błędów związanych z brakiem odpowiednich bibliotek należy koniecznie do polecenia dodać flagę -lpthread. Zakładając że nasz program nazwiemy "main.c".

gcc main.c -o main -lpthread
Krok 9
10
Możemy teraz przetestować program wykonując go. Jeśli nie będziemy mieli praw do wykonania programu używamy jako superużytkownik polecenia chmod +x na programie. Gdy posiadamy prawa do programu wpisujemy w shellu (np. bash):
./main

Program powinien się wykonać lub wskazać błąd - np. jeśli brak jest zasobów systemowych do wykonania wątku.

Wykonując program wielowątkowy warto jest przemyśleć możliwość wykorzystania mechanizmów zastrzegania dostępu do zasobów systemowych poprzez tzw. mutex (mutual exclusion - wzajemne wykluczenie).
Krok 10
11

Uwagi i spostrzeżenia


  • Koniecznie podczas kompilacji dodaj flagę -lpthread. Proces kompilacji może być dostępny przy pewnych konfiguracjach tylko z poziomu superużytkownika.
  • Oceń tę poradę

    3.0
    (4 głosów)
    Twoja ocena:
    Zapisywanie głosu...

    Komentarze

    Komentarze (0)

    Zaloguj się, aby dodać komentarz.

    Brak komentarzy. Bądź pierwszy!

    Ta strona używa plików cookies

    Używamy cookies dla działania serwisu i analizy ruchu. Polityka prywatności