36
Tak jak pthread_create () rozdziela dany program na dwa wątki, funkcja pthread_j oin () scala dwa wątki w jeden.
int pthread_join(pthread_t tid, vdid **status)
Pobiera ona dwa argumenty:
• ID wątku, na który chcemy poczekać.
• Wskaźnik zmiennej void*, w której zachowana zostanie wartość zwrócona przez wątek - jeśli nie jest nam potrzebna, wpisujemy NULL.
Czasem przydaje się możliwość sprawdzenia, który wątek jest wykonywany. Funkcja pthread_self () zwraca ID wątku, w którym zostanie wywołana. ID wątku można porównywać z innym za pomocą funkcji pthread_equal (). Funkcję tę można wykorzystać do sprawdzenia, czy dany wątek odpowiada aktualnemu wątkowi, ponieważ błędem jest wywołanie przez wątek funkcji pthread_join () w odniesieniu do tego samego wątku.
if (!pthread_equal (pthread_self (), other_thread)) pthread_join (other_thread, NULL)
Atrybuty wątków umożliwiają sterowanie zachowaniem wątku. Tworząc nowy wątek, do jego skonfigurowania nie musimy korzystać z wartości domyślnych, ale możemy utworzyć i ustawić własny obiekt atrybutów wątku. W tym celu należy:
• Utworzyć obiekt pthread_attr_t poprzez deklarację zmiennej automatycznej tego typu.
• Wywołać funkcję pthread_attr_init, przekazując jej wskaźnik do utworzonego obiektu. Atrybuty zostaną zainicjowane wartościami domyślnymi.
• Zmodyfikować obiekt atrybutów nowymi wartościami atrybutów.
• Przekazać przy tworzeniu wątku wskaźnik do obiektu atrybutu.
• Wywołać funkcję pthread_attr_destroy, aby zwolnić obiekt atrybutów. Pojedynczego obiektu atrybutów można używać do zainicjowania wielu wątków. W przeciwieństwie do procesów wszystkie wątki w jednym programie współdzielą przestrzeń adresową, co umożliwia wątkom korzystanie z tych samych danych. Każdy wątek ma jednak swój własny stos wywołań, co pozwala na wykonywanie innego kodu i wywoływanie w normalny sposób funkcji (lokalne zmienne przechowywane na stosie tego wątku). Wątki mogą znajdować się w różnych stanach, co pokazano na rysunku 4.2.
Programowanie z użyciem wątków jest skomplikowane, ponieważ większość programów wielowątkowych w systemie wieloprocesorowym może wykonywać się w tym samym czasie. Dość skomplikowane jest debugowanie wielowątkowego programu, gdyż trudno jest powtórzyć zachowanie programu (raz będzie działał dobrze, innym razem się zawiesi - nie ma sposobu na to, aby zmusić system do uszeregowania wątków tak samo). Problemy z wielowątkowością wynikają z j ednoczesnego korzystania z tych samych danych.
Normalnie wątek kończy się, gdy jego funkcja zakończy działanie albo zostanie wywołana funkcja pthread_exit () o następującej postaci:
int pthread_exit(pthread_t id_watku)
Aby jeden wątek mógł przerwać inny, należy użyć funkcji pthread_cancel () i przekazać jej ID wątku, który ma być usunięty. Anulowany wątek zwraca specjalną wartość PTHREAD_CANCELED. Wątek pod względem anulowania może znajdować się w jednym z trzech stanów:
® Może być asynchronicznie anulowalny - w każdej chwili wykonania można go anulować.
o Może być synchronicznie anulowalny - żądania anulowania są kolejkowane, a wątek jest anulowany, gdy osiągnie określone miejsce wykonania, o Może nie być anulowalny - żądanie anulowania jest ignorowane.
Aby zmienić sposób anulowania wątku na asynchronicznie anulowalny, należy użyć funkcji pthread_setcanceltype (), podając jako pierwszy argument PTHREAD_CANCEL_ASYNCHRONOUS. Drugi argument, który można pozostawić