Wielowątkowość Programowanie w środowisku rozproszonym. Wykład 1.
Informacje organizacyjne Wymiar godzin: W-30, LAB-15 Zaliczenie wykonanie kilku programów i ich zaliczenie (w trakcie zajęć laboratoryjnych) Egzamin pisemny Materiały: www.ae.krakow.pl/~lulap 2
Program jednowątkowy Wątek - część programu, która moŝe być realizowana w sposób współbieŝny. Program jednowątkowy - składa się z jednej sekwencji instrukcji /tzw. wątek główny programu/ (w języku Java tworzą one treść metody main( ) w klasie bazowej). 3
Program wielowątkowy Z poziomu wątku głównego tworzone są inne, realizowane współbieŝnie, wątki; KaŜdy wątek moŝe tworzyć kolejne wątki; Wątki mogą korzystać ze wspólnych danych; Program wielowątkowy kończy pracę po zrealizowaniu wątku głównego i wszystkich pozostałych wątków. 4
Reprezentacja wątków w języku Java Wątek reprezentowany jest przez klasę będącą potomkiem klasy Thread, której najwaŝniejsze metody to: public Thread() - konstruktor obiektu reprezentującego wątek public Thread(String name) - konstruktor pozwalający nadać nazwę tworzonemu wątkowi public void run() - definiuje operacje realizowane w ramach wątku public void start() - wywołuje metodę run() 5
Definiowanie wątków za pomocą obiektów klasy Thread i pochodnych class Gwiazdka extends Thread public void run() for (int i = 0; i < 10;i++) System.out.print("*"); try sleep(1000); catch(interruptedexception e) 6
... class Plus extends Thread public void run() for (int i = 0; i < 10;i++) System.out.print("+"); try sleep(1000); catch(interruptedexception e) 7
... public class TworzenieWatkow1 public static void main(string [] args) Gwiazdka g = new Gwiazdka(); Plus p = new Plus(); g.start(); p.start(); System.out.print("KONIEC"); Wyniki działania programu KONIEC*++**++*+*+*+*+*+**+ Definicja metody sleep (w klasie Thread): public static void sleep(long millis) throws InterruptedException 8
Definiowanie wątku za pomocą klasy implementującej interfejs Runnable Obliczenia realizowane przez wątek opisane są w klasie implementujacej interfejs Runnable Interfejs Runnable definiuje nagłówek jednej metody: public void run() metoda ta definiuje operacje realizowane w ramach wątku. Przedstawiony mechanizm tworzenia wątków naleŝy stosować wtedy, gdy klasa reprezentująca wątek jest potomkiem klasy innej niŝ Thread (np. klasy Applet) i - z uwagi na jednokrotny charakter dziedziczenia w języku Java - nie moŝe dziedziczyć cech klasy Thread. Obiekt klasy implementującej interfejs Runnable naleŝy przekazać jako parametr konstruktora w trakcie tworzenia obiektu typu Thread. Uruchomienie wątku następuje za pomocą metody start(), która wywołuje metodę run(). 9
Przykład class Gwiazdka implements Runnable public void run() for (int i = 0; i < 10;i++) System.out.print("*"); try Thread.sleep(1000); catch(interruptedexception e) 10
... class Plus implements Runnable public void run() for (int i = 0; i < 10;i++) System.out.print("+"); try Thread.sleep(1000); catch(interruptedexception e) 11
... public class TworzenieWatkow2 public static void main(string [] args) Thread g = new Thread(new Gwiazdka()); Thread p = new Thread(new Plus()); g.start(); p.start(); System.out.print("KONIEC"); Wyniki działania programu KONIEC*+*+*+*+*+*+*+*+*+*+ 12
Korzystanie ze wspólnych zasobów Wątki mogą korzystać ze wspólnych zasobów, ale program powinien sterować dostępem do współuŝytkowanych obiektów. Do sterowanie dostępem do wspólnych zasobów słuŝy mechanizm synchronizacji. 13
Korzystanie ze wspólnych zasobów bez mechanizmu synchronizacji Przykład programu nie zawierającego mechanizmów synchronizacji - wspólnym zasobem jest standardowy strumień wyjściowy. class Watek1 implements Runnable public void run() for (int i = 1; i <= 10; i++) try Thread.sleep(100); catch (InterruptedException e) System.out.print("A"); 14
... class Watek2 implements Runnable public void run() for (int i = 1; i <= 10; i++) try Thread.sleep(100); catch(interruptedexception e) System.out.print("B"); 15
... public class WspolneZasoby public static void main(string [] args) Thread w1 = new Thread(new Watek1()); Thread w2 = new Thread(new Watek2()); w1.start(); w2.start(); System.out.println("KONIEC"); Wynik działania programu: KONIEC BABABAABBABABABAABBA 16
Sekcja krytyczna wątku Sekcja krytyczna wątku - fragment programu (będącego częścią wątku), z poziomu którego następuje odwołanie do wspólnego zasobu. W danej chwili tylko jeden wątek moŝe realizować kod tworzący sekcję krytyczną. 17
Schemat sekcji krytycznej Wątek 1 Wątek 2 sekcja krytyczna sekcja krytyczna Wspólny zasób 18
Realizacja sekcji krytecznej JeŜeli wątek A realizuje swoją sekcję krytyczną, to wątek B, po dojściu do fragmentu kodu tworzącego jego sekcję krytyczną, zostanie wstrzymany, aŝ do chwili zakończenia realizacji sekcji krytycznej przez wątek A. Po zakończeniu realizacji sekcji krytycznej wątku A realizacja wątku B zostanie wznowiona. 19
Monitor jako narzędzie realizacji sekcji krytycznej mechanizm pozwalający na blokowania dostępu do obiektu; blokowanie odbywa się poprzez zajęcie monitora obiektu; monitor moŝe zastać zajęty tylko przez jeden wątek; jeśli wątek A chce zająć monitor obiektu, który jest aktualnie w posiadaniu wątku B, to realizacja wątku A jest wstrzymywana do momentu zwolnienia monitora przez wątek B; kaŝdy obiekt występujący w programie posiada oddzielny monitor. Wątek 1 Wątek 2 sekcja krytyczna Monitor Wspólny zasób sekcja krytyczna 20
Monitor w języku Java synchronized (nazwaobiektu) //zajęcie monitora obiektu... instrukcje tworzące sekcję krytyczną... //zwolnienie monitora obiektu 21
Przykład class Watek1 implements Runnable public void run() synchronized (System.out) for (int i = 1; i <= 10; i++) try Thread.sleep(100); catch (InterruptedException e) System.out.print("A"); 22
... class Watek2 implements Runnable public void run() synchronized (System.out) for (int i = 1; i <= 10; i++) try Thread.sleep(100); catch(interruptedexception e) System.out.print("B"); 23
... public class WspolneZasoby public static void main(string [] args) Thread g = new Thread(new Watek1()); Thread p = new Thread(new Watek2()); g.start(); p.start(); System.out.println("KONIEC"); Wyniki działania programu: KONIEC AAAAAAAAAABBBBBBBBBB UWAGA: Program nie określa, który wątek zajmie monitor obiektu System.out jako pierwszy. Z tego powodu przy kolejnej realizacji programu moŝna uzyskać wynik: KONIEC BBBBBBBBBBAAAAAAAAAA 24