Zaawansowane programowanie w C++ (PCP)
Wykład 10 - boost Thread.
dr inż. Robert Nowak
8 czerwca 2007
Równoległość
I bardzo wolna reakcja człowieka
I wolne urządzenia wejścia - wyjścia (np. drukarki)
I bardzo szybkie procesory
można przeprowadzać obliczenia podczas obsługi urządzeń Pojęcie równoległości:
I na platformach jednoprocesorowych (jednordzeniowych)
I na platformach wieloprocesorowych (wielordzeniowych) wieloprocesowe systemy operacyjne
Aplikacje wielowątkowe
Wątek („lekki proces”), pozwala realizować niezależne ciągi instrukcji w ramach procesu. Wątki współdzielą kod i dane (przestrzeń adresową) oraz zasoby.
I lepiej wykorzystuje dostępną moc obliczeniową
I pozwalają na obsługę wielu zleceń równolegle
I mechanizm nie wprowadza dużych narzutów.
Stany wątku
gotowy wykonywany
blokowany
zatrzymany
wątki (2)
Współdzielone są:
I zmienne statyczne i globalne
I sterta (heap) i zmienne dynamiczne (adres jest unikalny niezależnie od wątku)
I obiekty automatyczne (na stosie) jeżeli dostęp jest przez wskaźnik lub referencje
I zasoby systemu operacyjnego (pliki, okna itp)
I kod wykonywany Niezależne są:
I rejestry, ciąg wykonywanych instrukcji, stos
I zmienne automatyczne
Program ma zawsze jeden wątek (funkcja main() ) - wątek główny lub inicjujący. Może tworzyć dodatkowe wątki.
Wątki a C++
C++ jest przygotowany do implementacji aplikacji wielowątkowych
I większość funkcji z biblioteki standardowej może być bezpiecznie używana w różnych wątkach
I należy używać bibliotek przeznaczonych do pracy wielowątkowej (np. obsługa sterty)
I zabronione funkcje (przechowują stan pomiędzy wołaniami)
I rand (<cstdlib>)
I strtok (<cstring>)
I asctime, ctime, gmtime, localtime (<ctime>) standard języka nie dostarcza mechanizmów tworzenia i synchronizacji wątków
boost::thread - wątki w C++
#include <boost/thread/thread.hpp>
//Funkcja główna wątku użytkownika void my_thread() { /* ... */ } //Można też użyć funktora class MyThread {
public:
//tutaj implementacja funkcji wątku użytkownika void operator()() { /* ... */ }
};
int main() {
boost::thread thrd(&my_thread); //Utworzenie i uruchomienie wątku thrd.join(); //Biezacy watek czeka na zakonczenie watku thrd }
Problemy z programowaniem równoległym
wyścigi (race conditions): wiele wątków pisze lub czyta tę samą pamięć → niewłaściwa wartość ( niezdefiniowane zachowanie ).
znajduje wolne miejsce
znajduje wolne miejsce
rezerwuje miejsce
rezerwuje miejsce
watek 1 watek 2
nr:12 wolne
nr:12 zajęte
nr:12 zajęte klient1
klient2
czas
rozwiązanie problemu: synchronizacja (blokady)
Blokady w boost
mutex (mutual-execution) jest używany do szeregowania dostępu do zasobu. Stany: zablokowany, odblokowany.
//Utworzenie obiektu służącego do synchronizacji boost::mutex mutex_resource;
/* ... */
{
//scoped_lock - zdobywanie jest inicjacją, //konstruktor: lock, destruktor: unlock
boost::mutex::scoped_lock scoped_lock(mutex_resource);
//Tutaj dostęp do zasobu }//Tutaj zwolnienie zasobu
boost::mutex boost::recursive_mutex
boost::try_mutex boost::recursive_try_mutex boost::timed_mutex boost::recursive_timed_mutex boost::read_write_mutex
boost::try_read_write_mutex boost::timed_read_write_mutex
Problemy przy stosowaniu blokad
I zakleszczenia (deadlock)
I zagłodzenia (starvation)
blokuj A
blokuj B
czas
Watek 1 Watek 2
blokuj B
blokuj A czeka na
zwolnienie B
czeka na zwolnienie A
problemy z usuwaniem błędów w aplikacjach wielowątkowych
I niektóre błędy są niepowtarzalne
I różne zachowanie się wersji debug od release
I debugger potrzebuje specjalnego wsparcia aby pokazać stany wątków
I testy na platformach z jednym procesorem (rdzieniem) mogą nie pokazywać błędów które wystąpią na platformach
posiadających wiele procesorów (rdzieni)
I trudno testować wszystkie możliwe przebiegi sterowania
Typowe kończenie wątku
nie ma możliwości przerwania wątku z zewnątrz
class MyThread { public:
MyThread() : finish_(false) {}
void finish() { finish_ = true; } void operator()() {
while(!finish_) {
/* tutaj część przetwarzania */
/* a następnie sprawdzanie warunku !finish_ */
} } private:
volatile bool finish_;
};
Podsumowanie
I aplikacje wielowątkowe są coraz bardziej powszechne
I boost zapewnia obiekty reprezentujące wątki oraz mechanizmy synchronizacyjne
I wątki i mechanizm wyjątków