Watki11


Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 1
Wątki
1 Informacje wstępne
Wiele aplikacji ma do wykonania czynności które mogą być wykonane współbieżnie
ale muszą dzielić dane i inne zasoby. Można zastosować procesy ale koszt
komunikacji będzie znaczny. Lepszym rozwiązaniem jest abstrakcja wątku.
Tradycyjna implementacja procesu ma jeden wątek sterowania. W nowszych
systemach pojęcie procesu zostało rozszerzone  dopuszcza się istnienie wielu
wątków sterowania. Proces można podzielić na zbiór wątków i zestaw zasobów.
Proces  pojemnik na zasoby w ramach którego wykonują się watki.
Wątek  elementarna jednostka szeregowania korzystająca z zasobów procesu.
- Wątki wykonywane w ramach jednego procesu dzielą jego przestrzeń
adresową i inne zasoby procesu.
- W ramach jednego procesu może się wykonywać wiele wątków
1 proces, 1 wątek 1 proces, wiele wątków
...
...
wiele procesów, 1 wątkowych wiele procesów wielowątkowych
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 2
Atrybuty i zasoby własne wątku
1. Identyfikator wątka TID (ang.Thread Identifier) - każdy watek ma unikalny w
ramach procesu identyfikator. Jest to liczba całkowita. Pierwszy wątek ma TID
1, następny 2 itd.
2. Zestaw rejestrów (ang. Register set) - każdy wątek posiada własny obszar
pamięci w którym pamiętany jest zestaw rejestrów procesora (tak zwany
kontekst procesora). Gdy watek jest wywłaszczany lub blokowany w obszarze
tym pamiętane są rejestry procesora. Gdy watek będzie wznowiony obszar ten
jest kopiowany do rejestrów procesora.
3. Stos (ang. Stack) - każdy wątek ma swój własny stos umieszczony w
przestrzeni adresowej zawierającego go procesu. Na stosie tym pamiętane są
zmienne lokalne wątku.
4. Maska sygnałów (ang. Signal mask) - każdy wątek ma swą własną maskę
sygnałów. Maska sygnałów specyfikuje które sygnały mają być obsługiwane a
które blokowane. Początkowa maska jest dziedziczona z procesu
macierzystego.
5. Obszar TLS wątku (ang. Thread Local Storage)  każdy wątek ma pewien
obszar pamięci przeznaczony na utrzymywanie różnych danych
administracyjnych takich jak TID, PID, początek stosu, kod ewentualnego
błędu errno i inne dane. Obszar TLS jest odpowiednikiem deskryptora
procesu.
6. Procedura zakończenia (ang. Cancellation Handler) - gdy wątek się kończy
wykonywana jest procedura zakończenia w ramach której zwalniane są
zasoby wątku.
Wątek dzieli ze swym procesem macierzystym następujące zasoby:
" Dane statyczne (segment danych)
" Pliki
" Środowisko
" Katalog macierzysty
" Sesję, użytkownika, grupę
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 3
Deskryptor TLS 1
Kod
procesu P1
Licznik rozk. 1
Wątek W1
Dane
TLS 2
Licznik rozk. 2
Stos 1
Wątek W2
Stos 2
Pamięć RAM
Wątki 1 i 2 wykonywane w ramach procesu P1
Procesor Procesor Procesor
1 2 3
Szeregowanie
W21
W13 W12 W22
W11
Dane Zasoby Dane Zasoby
Proces 1 Proces 2
Procesy wielowątkowe
Rzeczywista równoległość
Wątki mogą być wykonywane na oddzielnych procesorach. Stąd model procesów
wielowątkowych nadaje się do wykorzystania na multiprocesorach ze wspólną
pamięcią (SMP  Shared Memory Processors) i zapewnia rzeczywistą równoległość
przetwarzania.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 4
Własności wątków
" Koszt utworzenia i przełączania wątku jest mniejszy niż procesu.
" Dane statyczne procesu są dla wątków działających w ramach jednego
procesu wzajemnie widoczne.
" Wykonanie każdego wątku przebiega sekwencyjnie, każdy wątek ma swój
licznik rozkazów.
" Wątki mogą być wykonywane na oddzielnych procesorach co umożliwia
przyspieszenie obliczeń.
" Ponieważ wątki dzielą wspólne dane konieczna jest synchronizacja dostępu
do tych wspólnych danych.
Zalety modelu wielowątkowego:
" Szybsza komunikacja pomiędzy wątkami wynikająca z mniej rygorystycznych
mechanizmów kontroli.
" Mniejszy koszt tworzenia / kończenia wątku niż procesu
" Zwykle szybszy czas przełączania wątków niż procesów .
" Możliwość przetwarzania wieloprocesorowego SMP w systemach ze wspólną
pamięcią (ang. Symetrical Multi Procesing).
Wobec szybko malejących kosztów komputerów wieloprocesorowych ta ostatnia
cecha nabiera szczególnie dużego znaczenia.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 5
2 Rodzaje wątków
Klasyfikacja
Wyróżniane są następujące typy wątków:
" Wątki poziomu jądra KLT - (ang. Kernel Level Tthreads).
" Wątki poziomu użytkownika ULT - (ang. User Level Threads).
" Rozwiązania mieszane
przestrzeń
użytkownika
szeregowanie
wewnętrzne
szeregowanie
poziomu jądra
przestrzeń
Proces Proces
jądra
wątki poziomu użytkownika wątki poziomu jądra
2.1 Wątki poziomu jądra
Jądro jest świadome istnienia wątków i szereguje je niezależnie. Proces używający
tych wątków w środowisku wieloprocesorowym może osiągnąć rzeczywistą
równoległość.
Zdefiniowanie działania wątków jądra wymaga rozstrzygnięcia wielu kwestii.
1. Problem dzielenia dostępu do plików przez wiele wątków (wskaznik bieżącej
pozycji pliku, zamknięcie).
2. Problem obsługi sygnałów trafiających do procesu (który wątek ma je
obsługiwać)
3. Problem widoczności wątków procesu przez inny proces (zwykle widoczność
tylko w ramach procesu).
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 6
2.2 Wątki poziomu użytkownika
Wątki poziomu użytkownika są tworzone bez wsparcia jądra. Kwanty czasu
przydzielane danemu procesowi, są dzielone pomiędzy zawarte w nim wątki.
Każdy taki wątek ma swój własny stos, miejsce do pamiętania rejestrów i innych
elementów kontekstu. Przełączanie kontekstów pomiędzy wątkami procesu odbywa
się bez udziału jądra przez specjalne biblioteki (np. pthreads).
W22
P2 W12
P2
W21
P1
P1
Czas Czas
Jądro przełącza procesy
W11, W12 - wątki procesu P1
P1 i P2
W11 W21, W22 - wątki procesu P2
Przypadek 1
Przypadek 2
Przypadek 1  Jądro przydziela czas procesora procesom P1 i P2
Przypadek 2  Wątki W11 i W12 wykonywane w ramach czasu przydzielonego
procesowi P1 przez jądro. Podobnie W21 i W22. W ramach jednego procesu
przełączanie wykonywane jest przez bibliotekę użytkownika.
2.3 Rozwiązania mieszane
Istnieją także rozwiązania pośrednie pomiędzy wątkami jądra a wątkami
użytkownika. Są to procesy lekkie (ang. Lightweighted processes) systemu Solaris.
W rozwiązaniu tym w jednym wątku poziomu jądra może istnieć kilka wątków
poziomu użytkownika.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 7
przestrzeń
użytkownika wątki poziomu
użytkownika
SU szeregowanie
poziomu
SU SU
użytkownika
szeregowanie
wątki poziomu jądra
poziomu jądra
przestrzeń
Proces
jądra
Zalety wątków użytkownika:
" Szybkość działania
" Zwiększenie stopnia współbieżności aplikacji.
Wady wątków użytkownika:
" Wywołanie funkcji blokującej proces wewnątrz wątku , wstrzymuje inne wątki.
" Brak możliwości zrównoleglenia (wykonania na wielu procesorach).
Mniejsza szybkość wątków jądra wynika z konieczności przełączenia trybu user /
kernel w przypadku wykonania funkcji systemowych.
Wyniki testów:
Zastosowanie wątków poziomu użytkownika przyspiesza przełączanie o ok. rząd
wielkości.
Null fork  utworzenie i zakończenie pustego procesu
Signal  Wait  wysłanie sygnału do innego wątku i oczekiwanie na odpowiedz.
Wątki poziomu użytkownika Wątki poziomu jądra Procesy
Null fork 34 948 11300
Signal - Wait 37 441 1840
Czasy w MS maszyna VAX system UNIX
Kiedy opłacalne jest stosowanie wątków zależy od udziału operacji przełączania
kontekstu w całości. Zależy od natury aplikacji.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 8
Liczba wątków / Opis Przykłady
liczba procesów
1:1 Każdy proces posiada jeden wątek Unix
M:1 Wiele wątków w ramach jednego Windows NT, Solaris,
procesu Linux
1:P Wątek może migrować pomiędzy Clouds, Emerald
procesami które mogą być
wykonywane na różnych
maszynach.
M:P Wątki wykonywane w ramach TRIX
domeny pomiędzy którymi mogą
migrować.
Niezbędny do operowanie na wątkach zestaw funkcji interfejsowych:
Aby umożliwić operowanie na wątkach niezbędny jest pewien zestaw funkcji
interfejsowych. Powinny być udostępnione następujące grupy funkcji:
" Tworzenie wątków i ich kasowanie.
" Synchronizacja dostępu do wspólnych danych (muteksy, semafory).
" Komunikacja pomiędzy wątkami.
" Nadawanie priorytetów wątkom.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 9
2.4 Kanoniczne stany wątku
Wykonywany Właśnie wykonywany przez procesor
Gotowy Posiadający wszyskie zasoby oprócz procesora
Zablokowany Brak pewnych zasobów
Zombie Zakończony ale nie dołączony do wątku macierzystego
(wątek dołączalny)
Nieistniejący Nie utworzony lub zakończony
wake-up
preempt
wyko- zablokow
gotowy block
nywany any
dispatch
create exit
exit
nie
join zombie
istniejący
Diagram stanów kanonicznych wątków
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 10
2.5 Wątki w Windows2000
Własności ogólne:
" Implementuje model procesów wielowątkowych
" Procesy implementowane są jako obiekty
" Wątki mogą być wykonywane na oddzielnych procesorach.
Proces  jednostka która posiada zasoby (pliki, segmenty pamięci)
Wątek  jednostka szeregowania
Proces posiada następujące zasoby:
" Przepustka bezpiecznego dostępu (ang. Access security token)
" Ciąg bloków definiujących wirtualna przestrzeń adresową
" Tablicę obiektów używanych przez proces (wątki, pliki, segmenty pamięci
dzielonej)
przepustka
obszary wirtualnej przestrzeni adresowej
Proces S1 S2 S3 S4 S2
O1 wątek
uchwyt 1
O2 wątek
uchwyt 2
O3 plik
uchwyt 3
... sekcja
tablica obiektów
Procesy i ich zasoby w Windows 2000
" Proces musi posiadać przynajmniej jeden watek
" W systemie wieloprocesorowym wątki mogą wykonywać się równolegle
Atrybut procesu Opis
Identyfikator PID
Deskryptor Zestaw informacji określający kto jest twórcą procesu, kto ma do
zabezpieczeń niego dostęp, w jaki sposób korzystać można z zasobów
Priorytet główny Informacja do szeregowania wątków
Domyślna rodzina Grupa procesorów na których mogą być przetwarzane watki
procesorów procesu
Przydzielone limity Limity pamięci, plików, czasu procesora
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 11
Czas Całkowity czas przetwarzania zużyty przez wątki
przetwarzania
Liczniki operacji Zmienne opisujące operacje we/wy wykonane przez wątki
we/wy
Licznik operacji Zmienne opisujące wykorzystanie pamięci wirtualnej
pamięci wirtualnej
Porty obsługi Kanał informacji przez który wysyłana jest informacja o awarii
wyjątków wątku
Stan w chwili Przyczyna zakończenia
zakończenia
Atrybuty procesu w Windows 2000
Tworzenie procesu
Uzyskanie atrybutów procesu
Uzyskanie PID procesu bieżącego
Zakończenie procesu
Metody działające na procesach
Atrybut wątku Opis
Identyfikator Identyfikator wątku
Kontekst wątku Zestaw informacji koniecznych do zawieszenia  wznowienia
watki
Priorytet Priorytet w danej chwili
dynamiczny
Rodzina Grupa procesorów na których może być przetwarzany wątek
procesorów wątku (podzbiór rodziny procesorów procesu)
Czas Całkowity czas przetwarzania zużyty przez wątek
przetwarzania
Stan alarmu Znacznik wskazujący czy wątek powinien uruchomić
asynchroniczne wywołanie procedury
Wskaznik liczby Liczba wskazująca ile razy wątek był zawieszany
zawieszeń
Przepustka Informacje o zabezpieczeniach
Port obsługi Kanał informacji przez który wysyłana jest informacja gdy wątek
zakończenia wątku spowoduje wyjątek
Stan w chwili Przyczyna zakończenia wątku
zakończenia
Atrybuty wątku w Windows 2000
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 12
Tworzenie wątku
Uzyskanie atrybutów wątku
Uzyskanie PID wątku bieżącego
Kończenie wątku
Zawieszenie wątku
Wznowienie wątku
Alarmowanie wątku
Testowanie alarmu wątku
Rejestrowanie portu zakończenia
Metody działające na wątkach
Gotowy wątek zdolny do natychmiastowego działania
Rezerwowy Oczekuje na uruchomienie gdy tylko procesor stanie się wolny.
Gdy priorytet wątku rezerwowego jest wyższy od działającego
może on zostać wywłaszczony.
Działający Wykonywany aż do wyczerpania kwantu czasu, wywłaszczenie
lub zakończenie
Oczekujący Wątek wchodzi w stan oczekiwania na skutek:
" Oczekiwanie na zakończenie operacji we/wy
" Z powodu synchronizacji
" Zlecenia zewnętrznego
W fazie Ustała przyczyna blokady ale zasoby są dostępne (np. stos w
przejściowej pamięci wymiany)
Zakończony
" Samoistnie
" Zakończony przez inny watek
" Zakończenie procesu macierzystego
Stany wątku w Windows 2000
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 13
Zdolny do dzialania
przelączenie
rezerwowy
wskazanie do
uruchomienia
gotowy wywlaszczenie dzialający
zakończenie
zasoby odblokowanie -
dostępne zasoby dostępne
zawieszenie
w fazie
oczekują
zakończo
przej
odblokowanie - cy
ny
ściowej
zasoby nie
dostępne
Niezdolny do dzialania
Stany wątku w Windows 2000
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId // thread identifier
)
Funkcja tworzenia wątku
Synchronizacja wątków:
Obiekty synchronizacyjne
" TSynchroMutex
" TsynchroCriticalSection
Operacje:
DoLock(Timeout: DWORD)
DoUnlock()
IsLocked()
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 14
2.6 Biblioteka pthreads
Zestaw funkcji dotyczący wątków zdefiniowany został przez normę POSIX P1003.4a
i nosi nazwę pthreads (skrót od Posix threads). Implementacja pakietu istnieje
między innymi w systemie Linux, QNX6, DEC OSF1. Obecnie wątki są elementem
biblioteki glibc (Od wersji 2).
Podstawowe operacje na wątkach
Zarządzanie wątkami Tworzenie i kasowanie wątków, czekanie na
zakończenie, inicjowanie zakończenia.
Operowanie na muteksach Zabezpieczenie dostępu do wspólnych danych.
Tworzenie i kasowanie muteksów, zajmowanie i
zwalnianie muteksów.
Operowanie na zmiennych Używane do sychronizacji wątków.
warunkowych Tworzenie i kasowanie zmiennych warunkowych,
zawieszanie i wznawianie wątków.
2.7 Zarządzanie wątkami
pthread_create
Tworzenie wątku
pthread_exit
Zakończenie wątku bieżącego
pthread_join
Czekanie na zakończenie wątku
pthread_attr_init
Inicjacja atrybutów wątku
pthread_attr_setdetachstate
Ustalanie trybu zakończenia wątku
pthread_self
Pobranie identyfikatora wątku
pthread_yield
Zwolnienie procesora
pthread_cancel
Kasowanie innego wątku
Tworzenie wątku
Nowy wątek tworzy się przy pomocy funkcji pthread_create. Funkcja ta tworzy
wątek, którego kod znajduje się w funkcji podanej jako argument func. Wątek jest
uruchamiany z parametrem arg, a informacja o nim jest umieszczana w strukturze
thread.
int pthread_create( pthread_t *thread,
pthread_attr_t *attr,
void (* func)(void *), *arg)
thread
identyfikator wątku  wartość nadawana przez funkcję
attr
atrybuty wątku, gdy NULL przyjęte domyślne
func
procedura zawierająca kod wątku
arg
argument przekazywany do wątku
Funkcja zwraca: 0  sukces, -1  błąd.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 15
Kończenie wątku
Wątek może być zakończony w następujące sposoby:
" Następuje powrót z procedury określającej kod wątku.
" Wątek wykonuje funkcję pthread_exit().
" Wątek jest kasowany przez inny wątek.
" Następuje zakończenie procesu macierzystego wątku.
Jawne zakończenie wątku następuje poprzez wywołanie procedury:
pthread_exit(void * status)
status
Kod powrotu wątku
Możliwe są dwa sposoby postępowania z kończonymi wątkami:
1. Z chwilą zakończenia się wątku zwalniane są wszystkie jego zasoby.
2. Zasoby zwalniane są z chwilą dołączenia wątku bieżącego do innego wątku
(wykonującego funkcję pthread_join).
Postępowanie to uzależnione jest od ustawienia atrybutu
PTHREAD_CREATE_JOINABLE który ustalany jest podczas tworzenia wątku.
1. Gdy atrybut ten nie jest ustawiony, wątek zwalnia swe zasoby zaraz po
zakończeniu.
2. Gdy atrybut jest ustawiony, wątek zwalnia zasoby po dołączeniu do innego
wątku.
Oczekiwanie na zakończenie wątku.
Proces bieżący może czekać na zakończenie innego wątku poprzez wywołanie
funkcji pthread_join.
int pthread_join( pthread_t *thread, void *status)
thread
identyfikator wątku  wartość nadawana przez funkcję
status
Kod powrotu zwracany przez zakończony wątek
Gdy wskazany jako parametr wątek nie zakończył się jeszcze, wątek bieżący jest
wstrzymywany.
Funkcja zwraca: 0  sukces, -1  błąd.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 16
W1
W1
pthread_create( )
pthread_create( )
W2 W2
pthread_join( )
pthread_exit( )
pthread_exit( )
pthread_join( )
W2 czeka na W1 W1 czeka na W2
Sposób kończenia wątku zależny jest od atrybutu PTHREAD_CREATE_JOINABLE.
Według standardu POSIX nowo tworzone wątki domyślnie mają ustawiony ten
atrybut a więc są dołączalne.
W3 i W4
W1 i W2
ustawiony atrybut
ustawiony atrybut
PTHREAD_CREATE_DETACHED
PTHREAD_CREATE_JOINABLE
pthread_create(...)
Zakończenie
pthread_exit(...)
Zakończenie i
zwolnienie
zasobów
pthread_join(...)
Zwolnienie
zasobów
Atrybuty są przekazywane do wątku w chwili jego tworzenia jako wartość parametru
attr funkcji pthread_create. Aby ustawić jawnie sposób kończenia wątku należy:
1. Zadeklarować zmienną attr typu pthread_attr_t .
2. Zainicjować zmienną za pomocą funkcji pthread_attr_init(&attr)
3. Ustawić sposób kończenia wątku poprzez wywołanie funkcji
pthread_attr_setdetachstate(&attr,at). Wartości parametru at
dane są w poniższej tabeli.
4. Zwolnić pamięć zajmowaną przez atrybut poprzez wykonanie funkcji
pthread_attr_destroy (&attr).
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 17
Wartość parametru at Działanie
PTHREAD_CREATE_DETACHED
Zasoby wątku zwalniane tuż po jego zakończeniu
PTHREAD_CREATE_JOINABLE
Zasoby wątku zwalniane po wykonaniu
pthread_join(...)
void *kod(void *data){
....
return (void *) cos;
}
main(void) {
pthread_t thr;
pthread_attr_t attr;
int status;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&thr, &attr, kod,0);
....
pthread_join(thr,(void *) &status);
pthread_attr_destroy(&attr)
}
Przykład ustawiania atrybutów wątku, utworzenia i oczekiwania na zakończenie
Inne atrybuty wątków
Oprócz sposobu zakończenia wątków można ustawiać także inne atrybuty wątków
jak np. stategia szeregowania (SCHED_RR, SCHED_FIFO,SCHED_OTHER).
Uzyskanie własnego identyfikatora
Wątek może uzyskać własny identyfikator poprzez wywołanie funkcji:
pthread_t pthread_self(void)
Zwolnienie procesora
Wywołanie funkcji pthread_yield powoduje przekazanie sterowania do
procedury szeregującej która wybierze następny wątek do wykonania.
int pthread_yield(void)
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 18
/* Kompilacja: cc thread1.c -o thread1 -lpthread */
#include
#include
#define NUM_THREADS 6
#define KROKOW 16
pthread_t tid[NUM_THREADS]; // Tablica identyfik. watkow
void * kod(void *arg);
int main(int argc, char *argv[]) {
int i;
// Tworzenie watkow -------------
for (i = 0; i < NUM_THREADS; i++)
pthread_create(&tid[i], NULL, kod,(void *)(i+1));
// Czekanie na zakonczenie ------
for (i = 0; i < NUM_THREADS; i++)
pthread_join(tid[i], NULL);
printf("watki zakonczone \n");
return 0;
}
void * kod(void *arg) {
int numer = (int)arg;
int i;
printf("watek: %d numer: %d \n", getpid(), numer);
for(i=0;i printf("watek %d krok %d \n",numer,i);
sleep(1);
}
return (NULL);
}
Tworzenie, wykonanie i kończenie wątków
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 19
2.8 Przekazywanie danych do wątku i pobieranie wyników
Parametry wątku
Funkcja realizująca wątek ma tylko jeden parametr będący wskaznikiem do typu
void.
void * kod(void *arg)
Aby przekazać do wątku większą niż jeden liczbę parametrów należy się posłużyć:
1. strukturą
2. tablicą.
typedef struct {
int pocz;
int kon;
int numer;
} param_t;
Wyniki wątku
Wątek powinien zwracać wskaznik na void poprzez:
1. Wykonanie return res
2. Wykonanie funkcji pthread_exit(void *res)
Wartość ta może być odczytana w funkcji:
int pthread_join( pthread_t *thread, void *status)
pthread_create((&tid, NULL,
kod,NULL)
pthread_exit((void *) res)
pthread_join(tid,&status)
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 20
typedef struct {
int pocz;
int kon;
int numer;
} param_t;
int main(int argc, char *argv[]){
param_t arg;
int wynik;
...
for (i = 0; i < NUM_THREADS; i++) {
arg.pocz = ...;
arg.kon = ...;
arg.numer = i;
pthread_create(&tid[i], NULL, znajdz,&arg);
}
...
// Czekanie na zakonczenie ------
for (i = 0; i < NUM_THREADS; i++) {
pthread_join(tid[i], (void*)&wynik);
printf( Watek: %d wynik: %d\n ,i,wynik);
}
}
void *znajdz(void *arg) {
int x1,x2,num,res;
param_t *par;
par = (param_t *)arg;
x1 = par->pocz;
x2 = par->kon;
num = par->numer;
printf("watek: %d pocz: %d kon: %d \n",num,x1,x2);
...
res = ...;
return((void *) res);
}
Przykład przekazywania parametrów do wątku i uzyskiwania wyników
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 21
Anulowanie wątku
Normalnym sposobem zakończenia się wątku jest:
1. wykonanie instrukcji return lub
2. funkcji pthread_exit.
Wtedy wątek sam podejmuje decyzję o swym zakończeniu.
Możliwe jest jednak aby jeden wątek zakończył inny. Używana jest do tego celu
funkcja pthread_cancel.
int pthread_cancel(pthread_t *thread) POSIX
Gdzie:
Identyfikator kasowanego wątku
thread
Należy unikać anulowania wątków przez inne watki.
Powodem jest fakt że wątek mógł pobrać pewne zasoby systemowe (pamięć, pliki) i
rozpocząć pewne akcje synchronizacyjne (np. zająć muteks). Gdy zostanie on
zakończony w przypadkowym punkcie wykonania może nie zwrócić pobranych
zasobów ani też nie zakończyć rozpoczętych akcji synchronizacyjnych. Skutkować
to może wyciekaniem zasobów lub wręcz blokadą aplikacji.
Procedura czyszcząca - funkcja która będzie wykonana automatycznie gdy wątek
będzie anulowany i jej zadaniem jest zwolnienie pobranych przez wątek zasobów.
Funkcja czyszcząca jest aktywowana poprzez wykonanie funkcji
pthread_cleanup_push
Funkcja czyszcząca jest deaktywowana poprzez funkcję pthread_cleanup_pop
lub poprzez normalne zakończenie się wątku.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 22
2.9 Dostęp do wspólnych danych
Wątki dzielą wspólny obszar danych. Stąd współbieżny dostęp do danych
może naruszyć ich integralność. Należy zapewnić synchronizację dostępu do
wspólnych danych. W bibliotece pthreads do zapewnienia wyłączności dostępu do
danych stosuje się mechanizm muteksu (ang. mutex). Nazwa ta pochodzi od słów
Mutual exclusion czyli wzajemne wykluczanie.
Inicjacja muteksu
pthread_mutex_init
Zajęcie muteksu
pthread_mutex_lock
Zwolnienie muteksu
pthread_mutex_unlock
Skasowanie muteksu
pthread_mutex_destroy
Deklaracja muteksu
Muteks jest obiektem abstrakcyjnym który może być w dwu stanach: wolny i zajęty.
Na muteksie wykonuje się dwie podstawowe operacje: zajęcie i zwolnienie.
Biblioteka pthreads definiuje muteks jako typ pthread_mutex_t. Przed użyciem
obiekt typu muteks musi być zadeklarowany. Przykładowo muteks o nazwie blokada
deklaruje się jak poniżej.
pthread_mutex_t blokada;
Inicjacja muteksu
Przed użyciem muteks musi być zainicjowany. Inicjacja następuje poprzez
wykonanie funkcji:
int pthread_mutex_init(pthread_mutex_t *mutex,
pthread_mutexattr_t *attr)
mutex
Zadeklarowana wcześniej zmienna typu pthread_mutex_t.
attr
Atrybuty muteksu. Gdy attr jest równe NULL przyjęte będą wartości
domyślne.
Funkcja zwraca: 0  sukces, -1  błąd.
Zainicjowany muteks pozostaje w stanie odblokowania.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 23
Zablokowanie dostępu do zasobu
Przed dostępem do zasobu należy zapewnić sobie wyłączność w korzystaniu z tego
zasobu. W tym celu wątek wykonuje funkcję:
int pthread_mutex_lock(pthread_mutex_t *mutex);
mutex
Zadeklarowana wcześniej i zainicjowana zmienna typu
pthread_mutex_t
Działanie funkcji zależy od stanu w jakim znajduje się muteks.
1. Gdy muteks jest wolny, następuje jego zablokowanie.
2. Gdy muteks jest zajęty, próba jego powtórnego zajęcia powoduje
zablokowanie się wątku który tę próbę podejmuje.
Odblokowanie dostępu do zasobu
Użyty i zablokowany wcześniej zasób powinien być zwolniony. Zwolnienie zasobu
odbywa się poprzez wywołanie funkcji:
int pthread_mutex_unlock(pthread_mutex_t *mutex)
mutex
Zadeklarowana wcześniej i zainicjowana zmienna typu
pthread_mutex_t
Działanie funkcji zależy od tego czy inne wątki czekają zablokowane na muteksie.
1. Brak wątków zablokowanych na muteksie  stan muteksu zostaje zmieniony
na wolny.
2. Są wątki zablokowane na muteksie  jeden z czekających wątków zostaje
odblokowany.
Thread 2
Thread 1
mutex_lock(mutex)
blokada
mutex_lock(mutex)
użycie zasobu
odblokowanie
mutex_unlock(mutex)
użycie zasobu
mutex_unlock(mutex)
Dwa wątki używają wspólnego zasobu chronionego przez mutex
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 24
Kasowanie muteksu
Kasowanie muteksu odbywa się poprzez wywołanie funkcji:
int pthread_mutex_destroy(pthread_mutex_t *mutex)
System zwalnia zasoby zajęte przez muteks. Muteks musi być wolny gdyż w
przeciwnym razie nie będzie skasowany i funkcja zwróci kod błedu.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 25
pthread_t wri;
int bufor[SIZE];
int new_item = 0;
int step = 0;
void *writer(void *arg);
void reader(void );
pthread_mutex_t mutex;
int main(int argc, char *argv[]) {
int i;
pthread_mutex_init(&mutex,NULL);
pthread_create(&wri, NULL, writer,NULL);
reader();
pthread_join(wri, NULL);
printf("watki zakonczone \n");
return 0;
} /* main */
// Watek piszacy do bufora
void * writer(void *arg){
int i;
while(1) {
pthread_mutex_lock(&mutex);
// while(new_item == 1);
if(new_item == 0) {
pisz(bufor);
new_item = 1;
}
pthread_mutex_unlock(&mutex);
}
return (NULL);
}
// Wątek czytający z bufora
void reader(void ) {
int i;
while(1) {
pthread_mutex_lock(&mutex);
// while(new_item == 0);
if(new_item == 1) {
czytaj(bufor)
new_item = 0;
}
pthread_mutex_unlock(&mutex);
}
}
Producenta / konsumenta  rozwiązanie z odpytywaniem
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 26
2.10 Inwersja priorytetów
Gdy dwa lub więcej wątki o różnych priorytetach używają wspólnego muteksu może
dojść zjawiska nazywanego inwersją priorytetów.
Dwa wątki, W1 o priorytecie wyższym i W2 o priorytecie niższym używają
zabezpieczonego muteksem wspólnego zasobu.
Scenariusz:
1. Jako pierwszy zajmuje muteks wątek W2 ( niższym priorytecie) a następnie wątek
W1 próbuje zająć muteks wykonując operację pthread_mutex_lock.
2. Startuje wątek W1. Muteks jest już zajęty, wątek W1 mimo że posiada wyższy niż
W2 priorytet nie będzie wykonywany.
3. Pojawia się wątek W3 o priorytecie pośrednim wywłaszczy on wątek W2 który nie
będzie mógł zwolnić muteksu. Wątek W1 pozostanie wciąż zablokowany a
wykonywał się będzie wątek W3 o priorytecie niższym niż W1.
Definicja 2-1 Inwersja priorytetów (ang. Priority Inversion)
Inwersja priorytetów  zjawisko polegające na wykonywaniu się wątku o niższym
priorytecie mimo że wątek o wyższym priorytecie pozostaje gotowy. Inwersja
priorytetów może się pojawić gdy wątki o różnych priorytetach używają wspólnego
muteksu lub podobnego mechanizmu synchronizacyjnego.
Jak postępować w takim przypadku?
Podbicie priorytetu (ang. priority boosting). Rozwiązanie to polega na tym że gdy
wątek W1 o wyższym priorytecie próbuje zająć muteks zajęty już przez wątek W2 o
priorytecie niższym to system podwyższa chwilowo priorytet wątku W2 zajmującego
muteks do wysokości priorytetu wątku W1.
Dzięki podwyższonemu priorytetowi wątek W2 szybciej wykona swe zadanie i zwolni
muteks. Po zwolnieniu muteksu wątkowi W2 zostaje mu przywrócony pierwotny
priorytet.
Definicja 2-2 Podbicie priorytetu (ang. Priority Boosting)
Podbicie priorytetu  tymczasowe zwiększenie priorytetu wątku przebywającego w
sekcji krytycznej do priorytetu wątku który oczekuje na wejście do sekcji krytycznej.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 27
wątek W1 wątek W2 wątek W3
priorytet 11 priorytet 9 priorytet 10
wątek W2
zajmuje muteks
mutex_lock(mutex)
odblokowanie
W3
mutex_lock(mutex)
wątek W1
wątek W2
zablokowany
zablokowany
na muteksie
mutex_unlock(mutex)
zablokowany zablokowany wykonywany
Rys. 2-1 Ilustracja zjawiska inwersji priorytetów
Przypadek sondy Pathfinder
Zjawisko inwersji priorytetów spowodowało awarię sondy marsjańskiej Pathfinder w
1997 roku. Po kilku dniach trwania misji sonda wykonała restart systemu co
spowodowało utratę zgromadzonych wcześniej danych.
Komputerem sterującym był system oparty na magistrali VME.
Do magistrali VME oprócz procesora dołączone były:
" Interfejs do radia
" Interfejs do kamery
" Interfejs do magistrali 1553 (dwuprzewodowa magistrala szeregowa
stosowana w lotnictwie)
Do magistrali 1553 dołączono: akcelerometr, radarowy miernik wysokości,
instrumenty meteorologiczne, sterowniki zaworów, sensory promieniowania
słonecznego. Interfejs do magistrali 1553 zbudowany jest na zasadzie pamięci
dwuportowej. Od strony VME widziany jest jako obszar pamięci dzielonej
Sonda wyposażona była w system VxWorks firmy Wind River Systems. System ten
stosuje wywłaszczającą strategię szeregowania wątków którym nadaje się priorytety.
W awarii brały udział trzy wątki:
1. Wątek zarządzający  szyną informacyjną magistrali 1553  wspólnym
obszarem pamięci dzielonej w którym inne wątki umieszczały swe dane.
Dane te były dostępne dla innych wątków. Ten watek miał wysoki priorytet.
2. Wątek przekazywania danych meteorologicznych  priorytet niski
3. Watek komunikacyjny  priorytet średni
Wspólny obszar pamięci był zabezpieczony muteksem.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 28
Scenariusz:
1. Watek meteorologiczny zajął muteks
2. Przerwanie odblokowało watek informacyjny który próbował zająć muteks ale
że był on zajęty to się zablokował
3. Wątek komunikacyjny o średnim priorytecie wywłaszczył watek
meteorologiczny który nie mógł zwolnić muteksu. Było to długotrwałe zadanie.
4. Watchdog timer zaobserwował że  szyna informacyjna nie działa i
przeprowadził restart całego systemu.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 29
2.11 Zmienne warunkowe
Muteksy są narzędziem zapewniającym ochronę sekcji krytycznej. Jak postąpić
gdy wewnątrz sekcji krytycznej wymagane jest oczekiwanie na spełnienie pewnego
warunku a więc synchronizacja z innym wątkiem. Podobny problem występuje w
monitorze gdzie używa się funkcji wait i signal. Biblioteka wątków dostarcza
narzędzia do rozwiązania takiego problemu synchronizacji. Narzędzie to nazywa się
zmienną warunkową (ang. condition variable).
Zmienna warunkowa jest narzędziem do blokowania wątku wewnątrz sekcji
krytycznej aż do momentu gdy pewien warunek zostanie spełniony. Warunek ten
może być dowolny i niezależny od zmiennej warunkowej. Zmienna warunkowa musi
być użyta w połączeniu z muteksem o ile konstrukcja ma zapewnić własności
monitora.
Przed użyciem zmienna warunkowa musi być zadeklarowana jako zmienna typu
pthreads_cond_t.
Najważniejsze operacje związane ze zmiennymi warunkowymi są dane poniżej.
Inicjacja zmiennej warunkowej.
pthread_cond_init
Zawieszenie wątku w kolejce.
pthread_cond_wait
Wznowienie wątku zawieszonego w kolejce danej
pthread_cond_signal
zmiennej warunkowej.
Wznowienie wszystkich wątków zawieszonych w
pthread_cond_brodcast
kolejce danej zmiennej warunkowej.
Skasowanie zmiennej warunkowej z zwolniene jej
pthread_cond_destroy
zasobów.
Inicjacja zmiennej warunkowej
int pthread_cond_init(pthreads_cond_t *zw,
pthreads_condattr_t attr)
Zadeklarowana wcześniej zmienna typu pthread_cond_t.
zw
Atrybuty zmiennej warunkowej. Gdy attr jest równe NULL przyjęte
attr
będą wartości domyślne.
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 30
Zawieszenie wątku w oczekiwaniu na sygnalizację
int pthread_cond_wait(pthreads_cond_t *zw,
pthread_mutex_t *mutex)
Zadeklarowana i zainicjowana zmienna typu pthread_cond_t.
zw
Zadeklarowana i zainicjowana zmienna typu pthread_mutex_t.
mutex
Funkcja powoduje zawieszenie bieżącego wątku w kolejce związanej ze zmienną
warunkową zw. Jednocześnie blokada mutex zostaje zwolniona. Obie operacje są
wykonane w sposób atomowy.
Gdy inny wątek wykona operację pthreads_cond_signal(&zw)
zablokowany wątek zostanie odblokowany a blokada mutex zwolniona.
Wznowienie zawieszonego wątku
int pthread_cond_signal(pthreads_cond_t *zw)
Zadeklarowana i zainicjowana zmienna typu pthread_cond_t.
zw
Jeden z wątków zablokowanych na zmiennej warunkowej zw zostanie zwolniony.
Wznowienie wszystkich zawieszonych wątków
int pthread_cond_brodcast(pthreads_cond_t *zw)
Zadeklarowana i zainicjowana zmienna typu pthread_cond_t.
zw
Wszystkie wątki zablokowane na zmiennej warunkowej zw zostaną zwolnione.
Typowa sekwencja użycia zmiennej warunkowej:
pthread_mutex_lock(&m)
...
while( ! warunek )
pthread_cond_wait( &cond, &m)
...
pthread_mutex_unlock(&m)
Wątek oczekujący na warunek
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 31
pthread_mutex_lock(&m)
...
ustawienie_warunku
pthread_cond_signal( &cond)
...
pthread_mutex_unlock(&m)
Wątek ustawiający warunek i sygnalizujący jego spełnienie
Wątek 1 Wątek 2
mutex_lock(m)
mutex_lock(m) blokada
odblokowanie
blokada cond_wait(c,m)
ustawienie
cond_signal(c)
warunku
odblokowanie
użycie zasobu
mutex_unlock(m)
odblokowanie
mutex_unlock(m)
Wątek 1 czeka na warunek ustawiany przez wątek 2
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 32
// Problem czytelników i pisarzy rozw. poprawne
pthread_mutex_t mutex; // Ochrona zmiennej count
pthread_cond_t cond; // Kolejka czekających
// Liczba czyt. w czytelni, -1 gdy jest tam pisarz
int count;
read_lock(void) {
mutex_lock(&mutex);
// Czytelnik czeka gdy w czytelni jest pisarz
while(count < 0)
mutex_lock(&cond,&mutex);
count++;
mutex_unlock(&mutex);
}
write_lock(void) {
mutex_lock(&mutex);
// Pisarz czeka na wolną czytelnie
while(count != 0)
mutex_lock(&cond,&mutex);
count--;
mutex_unlock(&mutex);
}
rw_unlock(void) {
mutex_lock(&mutex);
// Pisarz czeka na wolną czytelnie
if(count < 0) count = 0
else count --;
if(count == 0)
cond_brodcast(&cond);
mutex_unlock(&mutex);
}
void pisarz(void) {
while(1) {
rw_rdlock();
czytanie(...);
rw_unlock();
}
}
void czytelnik(void) {
while(1) {
rw_wrlock();
pisanie(...);
rw_unlock();
}
}
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 33
2.12 Implementacja semaforów za pomocą zmiennych
warunkowych
Za pomocą zmiennych warunkowych i muteksów można zaimplementować bardziej
wygodne narzędzie synchronizacji jakim jest semafor.
int sem_init(semaphore *s, int v) Inicjacja semafora s i ustawienie jego licznika
Count na wartość v
int sem_wait(semaphore *s); Gdy licznik Count = 0 czekaj
Gdy licznik Count > 0 to Count = Count -1
int sem_post(semaphore *s); Gdy jakiś proces czeka to odblokuj go.
Gdy nie Count = Count +1
int sem_destroy(semaphore *s); Kasowanie semafora
Podstawowe operacje semaforowe
Semafor jest wskaznikiem na strukturę która zawiera pola:
Nazwa pola Typ Funkcja
count
Zmienna całkowita Licznik semafora
mutex
Muteks Ochrona sekcji krytycznej semafora
cond
Zmienna warunkowa Kolejka semafora
S count W1 W2 Wn
conv
Semafor
mutex
Kolejka wątków czekających na
zmiennej warunkowej conv
// Plik semaphore.h
#include
#include
typedef struct semaphore {
int count; // Licznik semafora
pthread_mutex_t mutex; // Ochrona sekcji kr.
pthread_cond_t cond; // Kolejka semafora
}
int sem_init(semaphore *s, int val);
int sem_wait(semaphore *s);
int sem_post(semaphore *s);
int sem_destroy(semaphore *s);
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 34
Plik nagłówkowy implementacji semaforów
// Plik semaphore.c
#include  semaphore.h
sem_init(semaphore *s, int val) {
s->count = val;
if(pthread_mutex_init(&(s->mutex),NULL) == -1)
perror( sem_init - mutex );
if(pthread_cond_init(&(s->cond),NULL) == -1)
perror( sem_init - cond );
}
int sem_destroy(semaphore *s) {
if(pthread_mutex_destroy(&(s->mutex)) == -1)
perror( sem_destroy - mutex );
if(pthread_cond_destroy(&(s->cond),NULL) == -1)
perror( sem_destroy - cond );
}
int sem_wait(semaphore *s) {
int x;
pthread_mutex_lock(&(s->mutex));
while(s->count <= 0)
pthread_cond_wait(&(s->cond),&(s->mutex));
(s->count)--;
x = s->count;
pthread_mutex_unlock(&(s->mutex));
return(x);
}
int sem_post(semaphore *s) {
int x;
pthread_mutex_lock(&(s->mutex));
(s->count)++;
x = s->count;
pthread_mutex_unlock(&(s->mutex));
pthread_cond_signal(&(s->cond));
return(x);
}
Plik implementacji semaforów
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 35
2.13 Przykład  Znajdowanie liczb pierwszych
// Program jednowątkowy znajdowania liczb pierwszych
#include
int main(int argc, char * argv[]) {
int x1,x2,j;
int t1,t2;
int lpierw = 0;
if(argc < 3) {
printf("Uzycie: lbpierw l-pocz l-konc \n");
return 0;
}
x1 = atoi(argv[1]);
x2 = atoi(argv[2]);
t1 = time(NULL);
for(j=x1;j<=x2;j++) {
if(isPrime(j)) lpierw++;
}
t2 = time(t2);
printf("Liczb pierwszych: %d czas obl.:
%d\n",lpierw,t2-t1);
return(lpierw);
}
int isPrime(int n) {
int i;
for(i=2; i*i <= n; i++) {
if((n%i) == 0) return 0;
}
return 1;
}
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 36
Zarządca
n
parametr
1 i
pocz[0],pocz[1],
kon[0], kon[2],...
wykona- wykona- wykona-
tablice
wca 1 wca i wca n
liczb[0],liczb[1]
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 37
// Znajdowanie liczb pierwszych  progr. wielowatkowy
// Kompilacja: cc thread1.c -o thread1 -lpthread
// Uruchomienie: ./watki3 zakres
#include
#include
#define NUM_THREADS 4
pthread_t tid[NUM_THREADS]; // Tablica identyfik.
watkow
int pocz[NUM_THREADS];
int kon[NUM_THREADS];
int wynik[NUM_THREADS];
void *znajdz(void *arg);
int main(int argc, char *argv[])
{
int i,zakres,delta,sum = 0;
zakres = atoi(argv[1]);
delta = zakres / NUM_THREADS;
printf("zakres: %d delta: %d\n",zakres,delta);
// Tworzenie watkow -------------
for (i = 0; i < NUM_THREADS; i++) {
pocz[i] = delta *i;
kon[i] = delta * (i+1) -1;
printf("Start: %d pocz: %d kon:
%d\n",i,pocz[i],kon[i]);
pthread_create(&tid[i], NULL, znajdz,(void *)i);
}
// Czekanie na zakonczenie ------
for (i = 0; i < NUM_THREADS; i++)
pthread_join(tid[i], NULL);
for (i = 0; i < NUM_THREADS; i++)
sum = sum + wynik[i];
printf("watki zakonczone, wynik:%d \n",sum);
return 0;
}
Wątki
PDF created with pdfFactory trial version www.pdffactory.com
Jędrzej Ułasiewicz Programownie aplikacji współbieżnych str. 38
void *znajdz(void *arg) {
int j,x1,x2;
static int lpierw = 0;
int num = (int)arg;
x1 = pocz[num];
x2 = kon[num];
printf("watek: %d pocz: %d kon: %d \n",num,x1,x2);
for(j=x1;j<=x2;j++) {
if(isPrime(j)) lpierw++;
}
printf("Wynik: %d, liczb: %d \n",num,lpierw);
wynik[num] = lpierw;
return(NULL);
}
int isPrime(int n) {
int i;
for(i=2; i*i <= n; i++) {
if((n%i) == 0) return 0;
}
return 1;
}
Wątki
PDF created with pdfFactory trial version www.pdffactory.com


Wyszukiwarka

Podobne podstrony:
watki1 csproj FileListAbsolute (2)
watki1 csproj FileListAbsolute (2)
watki1 csproj FileListAbsolute

więcej podobnych podstron