Zaradni.pl

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...

krok 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 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 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 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 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, NULL, &funkcjaC, NULL))
{
printf("Nie udalo sie utworzyc watku: %d\n", 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 6

Tworzymy drugi wątek analogicznie do pierwszego:

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

Utworzyliśmy drugi wątek - teraz funkcja "funkcjaC" będzie wykonywana równolegle.

krok 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, NULL );
pthread_join( watek2, NULL );

krok 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 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 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).

Lista potrzebnych rzeczy:

  • kompilator GCC z wbudowanymi bibliotekami pthread.

Uwagi i ostrzeżenia:

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

Dodaj swój komentarz:

Autor porady

mmierzwinski

Właściciel i czołowy programista firmy Bluebox Software. Grafik samouk i uż…

kategoria: Programowanie, system Linux


Podobne porady

  1. Konkursy
  2. Program udziału w zyskach
  3. Zasady publikacji treści

  4. O serwisie
  5. Polityka prywatności
  6. Regulamin
  7. Unia Europejska
  8. Reklama
  9. Kontakt