Analiza mechanizmów wielowątkowości w Javie

Wielkość: px
Rozpocząć pokaz od strony:

Download "Analiza mechanizmów wielowątkowości w Javie"

Transkrypt

1 Politechnika Warszawska Wydział Elektroniki i Technik Informacyjnych Instytut Informatyki Rok akademicki 2014/2015 Praca dyplomowa magisterska Piotr Hryciuk Analiza mechanizmów wielowątkowości w Javie Opiekun pracy: dr inż. Łukasz Skonieczny Ocena Podpis Przewodniczącego Komisji Egzaminu Dyplomowego

2 Specjalność: Informatyka Inżynieria systemów informatycznych Data urodzenia: 27 lipca 1991 r. Data rozpoczęcia studiów: 24 lutego 2014 r. Życiorys Urodziłem się 27 lipca 1991 roku w Łosicach. W latach uczęszczałem do I Liceum Ogólnokształcącego w Łosicach. W 2010 roku zdałem egzamin maturalny i rozpocząłem studia na wydziale Elektroniki i Technik Informacyjnych, gdzie uzyskałem w 2014 roku tytuł inżyniera podpis studenta Egzamin dyplomowy Złożył egzamin dyplomowy w dn Z wynikiem Ogólny wynik studiów Dodatkowe wnioski i uwagi Komisji

3 Streszczenie Niniejsza praca omawia mechanizmy wielowątkowości dostępne na platformie Java. Pierwsza część pracy to analiza teoretyczna. Druga część to praktyczne zastosowanie mechanizmów oraz ich analiza w konkretnych przypadkach. Przedmiotem analizy mechanizmów wielowątkowości są algorytmy sortowania, grafowe oraz operacji na macierzach. Zbiory testowe zostały samodzielnie przygotowane bądź wygenerowane przez autora pracy. Słowa kluczowe: java, wielowątkowość, Prim, pule wątków, Cauchy, sortowanie, współbieżność, wątki. Abstract Title: Java concurrency mechanisms analysis. This thesis describes Java concurrency mechanisms. First part of the thesis describes theory behind each of mechanisms. The second part is focused on practical appliance of each of the mechanisms and analysis of their performance in certain cases. Algorithms are subject of analysis: sorting, graph algorithms, matrix multiplication. Test sets were prepared or generated by the author of the thesis. Key words: java, concurrency, Prim, thread pools, Cauchy, sorting, threads.

4 Spis treści 1 Wstęp Cel pracy Struktura pracy Współbieżność w Javie Co to jest wątek? Stany wątków Bezpieczeństwo wątków Różnice pomiędzy procesem a wątkiem Przełączanie kontekstu Model pamięciowy Javy Widoczność zmiennych współdzielonych Wyścigi Atomowość operacji Mechanizm ThreadPoolExecutor Mechanizm fork/join Prawo Amdahla Planista wątków Komunikacja między wątkami Omówienie przypadków testowych w wersji podstawowej Sortowanie przez scalanie mergesort Sortowanie szybkie quicksort Algorytm Prima wyznaczający minimalne drzewo rozpinające Mnożenie macierzy metodą Cauchy ego

5 SPIS TREŚCI 4 Implementacje wielowątkowe Środowisko testowe Sortowanie przez scalanie mergesort ThreadPoolExecutor Fork/Join Porównanie i wnioski Sortowanie szybkie quicksort Porównanie z metodami z Java Development Kit ThreadPoolExecutor Fork/Join Porównanie i wnioski Algorytm Prima wyznaczający minimalne drzewo rozpinające Metody synchronized ConcurrentLinkedQueue SynchronizedList Porównanie i wnioski Mnożenie macierzy metodą Cauchy ego CountDownLatch / ExecutorService Fork/Join Porównanie i wnioski Podsumowanie 67 A Załączniki 70 2

6 Rozdział 1 Wstęp Wykonywanie równocześnie wielu zadań jest skomplikowane zarówno dla człowieka jak i dla maszyny. Jednak od kilkudziesięciu lat informatycy na całym świecie mają możliwość sprostania temu zadaniu dzięki zastosowaniu programowania współbieżnego, które cechuje się szybkością i wydajnością, nie tracąc przy tym na bezpieczeństwie. Programowanie współbieżne stało się możliwe dzięki rozwojowi systemów operacyjnych zdolnych do wykonywania wielu procesów jak i wątków w obrębie nich. Niektóre problemy są z natury współbieżne możemy przedstawić rozwiązania takich problemów w postaci czytelnych, niezależnie wykonujących się procedur. Można rozważyć przypadek komputerowego zamodelowania pracy w fabryce, gdzie wiele postaci poruszałoby się na ekranie wykonując swoje zadania. Ruchy każdej z postaci można byłoby oprogramować w sposób sekwencyjny, rozważając działania wszystkich postaci w jednym fragmencie kodu. Jednakże o wiele bardziej bardziej korzystnym z punktu widzenia projektowania systemów rozwiązaniem jest oprogramowanie każdej postaci z osobna. Za pisaniem aplikacji wielowątkowych przemawia także czysty pragmatyzm pełniej wykorzystywane są dostępne zasoby, co wpływa na istotną poprawę wydajności. Pomimo wyżej wspomnianych zalet, takie rozwiązania wiążą się z dodatkowymi problemami np. wykrywaniem kolizji pomiędzy postaciami, unika- 3

7 1.1. CEL PRACY niem konfliktów itp. Można więc wnioskować, że programy współbieżne są trudniejsze w implementacji, ale dodatkowy wysiłek nagradzany jest większą wydajnością oprogramowania. 1.1 Cel pracy Celem niniejszej pracy magisterskiej jest porównanie mechanizmów wielowątkowości dostępnych w języku programowania Java. Jako model porównań posłużą wielowątkowe implementacje znanych algorytmów po kilka dla każdego algorytmu przy użyciu dostępnych mechanizmów wielowątkowości. Przekrój badanych mechanizmów waha się od konstrukcji wbudowanych bezpośrednio w język (np. wewnętrzne blokady, metody synchronized) do klas z pakietu java.util.concurrent. W rezultacie badań, oczekuje się uzyskania ciekawych wniosków oraz opracowania generalnych zaleceń dot. stosowania mechanizmów w zależności od rozważanego problemu. 1.2 Struktura pracy Praca poprzedzona jest rozdziałem teoretycznym, który opisuje ogólne pojęcia związane z programowaniem wielowątkowym oraz omawia zagadnienia związane z bezpieczeństwem wątków. Poruszany jest też temat zagrożeń jakie niesie ze sobą programowanie współbieżne oraz model pamięciowy wirtualnej maszyny Javy Java Memory Model. Następnie omawiane są używane w pracy mechanizmy i wzorce. W rozdziale trzecim opisane zostały rozważane algorytmy w wersji jednowątkowej. Zawarto również informacje na temat implementacji. Rozdział ten ma za zadanie przybliżyć istotę problemów, a także wskazać miejsca na potencjalne ulepszenia. Rozważane algorytmy to: sortowanie przez scalanie, sortowanie szybkie, algorytm Prima wyszukiwania minimalnego drzewa rozpinającego, algorytm mnożenia macierzy metodą Cauchy ego. Rozdział czwarty przedstawia implementacje każdego z omawianych algorytmów w sposób wielowątkowy. Przeprowadzona została również analiza 4

8 1.2. STRUKTURA PRACY każdej z implementacji skonkludowana wnioskami. Pracę kończy podsumowanie prac i osiągniętych efektów. 5

9 Rozdział 2 Współbieżność w Javie 2.1 Co to jest wątek? W Javie wątek może oznaczać dwie różne rzeczy: instancję klasy java.lang.thread, wątek wykonania. 1 Instancja klasy Thread jest po prostu obiektem Javy ma swoje zmienne i metody, powstaje oraz ginie na stercie. Wątek wykonania z kolei to niezależny, lekki proces, który ma swój stos wywołań. W Javie zawsze można mówić o dokładnie jednym stosie wykonań per wątek. Wątek w Javie powstaje jako instancja klasy java.lang.thread. W klasie tej można znaleźć szereg metod, które pozwalają na zarządzanie wątkiem poprzez akcje takie jak tworzenie, uruchamianie, pauzowanie. O kodzie który ma zostać wykonany w oddzielnym wątku można myśleć jak o pracy do wykonania. Wykonującym tę pracę (a więc wykonującym kod pracy do wykonania) jest wątek. Wykonanie pracy do wykonania zawsze rozpoczyna się od wywołania najważniejszej z metod klasy Thread, run(), która wygląda następująco: 1 Kathy Sierra, Bert Bates Java SE 7 Programmer I & II Study Guide. Oracle Press; 2014, s

10 2.1. CO TO JEST WĄTEK? public void run() { // Kod "pracy do wykonania" } Kod który ma zostać wykonany w osobnym wątku zawsze powinien znajdować się w ciele metody run() (oczywiście, można wywoływać z niej inne metody). To właśnie przy wywołaniu metody run() powstaje nowy wątek wykonania nowy stos wywołań. Wątki w Javie można zdefiniować i stworzyć w dwojaki sposób: poprzez dziedziczenie po klasie java.lang.thread, poprzez implementację interfejsu Runnable. Dziedziczenie po klasie java.lang.thread to najprostszy sposób, ale zazwyczaj nie jest to dobra decyzja w kontekście projektowania zorientowanego obiektowo. Wynika to z faktu, że dziedziczenie powinno być używane jako dostarczenie wyspecjalizowanej wersji klasy podstawowej a więc w tym wypadku, dostarczenie bardziej wyspecjalizowanego zachowania wątków. Zazwyczaj nie w tym rzecz. W typowej sytuacji nie jest bowiem pożądane tworzenie bardziej wyspecjalizowanej wersji wątku, a raczej dostarczenie zadania do wykonania przez wątek. W tym wypadku należałoby stworzyć klasę która implementuje interfejs Runnable. Dodatkową zaletą takiego rozwiązania jest fakt, że stworzona klasa wciąż może dziedziczyć po innej klasie, co nie byłoby możliwe przy wcześniej wspomnianej solucji. 2 Poniżej przykład klasy implementującej interfejs Runnable. class MyRunnable implements Runnable { public void run() { System.out.println("Wazne zadanie wykonujace sie w osobnym watku"); } } 2 W Javie klasa może dziedziczyć tylko po jednej innej klasie, ale może implementować wiele interfejsów. 7

11 2.2. STANY WĄTKÓW Jest to definicja zadania, które zostanie wykonane w osobnym wątku. Aby sprawić by to się stało, należy zainicjować wątek. W przypadku klasy, która dziedziczy po klasie java.lang.thread, jest to bardzo proste: MyThread thread = new MyThread(); W przypadku klasy implementującej interfejs Runnable wygląda to następująco: MyRunnable myrunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); W każdym z tych przypadków, po wykonaniu kodu otrzymujemy gotowy obiekt klasy java.lang.thread. Teraz pozostaje stworzenie nowego wątku wykonania a więc nowego stosu wykonania. Odbywa się to poprzez wywołanie metody start(): thread.start(); 2.2 Stany wątków Wątek w Javie może znajdować się w jednym z pięciu stanów: Nowy (ang. new) Jest to stan w którym wątek znajduje się, gdy został już utworzony egzemplarz klasy java.lang.thread, ale metoda start() nie została jeszcze wywołana na tym wątku. Stąd mamy tutaj do czynienia z czynnym obiektem javowym instancją klasy Object ale nie z wątkiem wykonania. Wątki będące w stanie nowy są uznawane za wątki nieżywe. Uruchamialny (ang. runnable) Jest to stan w którym wątek jest kwalifikujący się do uruchomienia, ale planista wątków nie wybrał tego wątku jako wątku do uruchomienia. Wątek przechodzi do stanu uruchamialnego w momencie kiedy wywołana zostaje metoda start(). Wątek może powrócić do tego po tym jak był wykonywany, lub jako 8

12 2.2. STANY WĄTKÓW przejście ze stanu uśpienia, zablokowania czy oczekiwania. Kiedy wątek jest uruchamialny, uwaza się go za wątek żywy. Uruchomiony (ang. running) Jest to stan w którym wątek znajduje się po wyborze przez planistę wątków z puli wątków kwalifikujących się do uruchomienia, jako obecnie wykonywany proces. Wątek może przejść ze stanu uruchomiony do innego stanu z różnorakich powodów. Jednym z nich może być po prostu rozkaz planisty wątków. W przeciwieństwie do stanu uruchamialny, aby wątek znalazł się w stanie uruchomiony istnieje wyłącznie jeden sposób wątek musi zostać wybrany przez planistę wątków. Oczekujący/zablokowany/uśpiony (ang. waiting/blocked/sleeping) Jest to stan w którym wątek znajduje się, gdy nie kwalifikuje się do uruchomienia. W nazwie widoczne są aż trzy stany, ale można byłoby je uogólnić do jednego: wątek jest żywy, ale nie kwalifikuje się do przejścia w stan uruchomiony. Gdy wątek znajduje się w tym stanie, oznacza to, że nie jest uruchamialny, ale może znaleźć się w tym stanie za jakiś czas na skutek jakiegoś zdarzenia. Wątek może być oczekujący, gdy kod uruchomieniowy wątku każe mu czekać. W takim wypadku zdarzenie które powoduje przejście z powrotem do stanu uruchamialny, sprawia, że inny wątek przesyła powiadomienie, że nie jest już konieczne aby wątek znajdował się w stanie oczekiwania. Ważnym faktem jest, że jeden wątek nie może rozkazać drugiemu aby ten się zablokował. Częstą pomyłką programistów rozpoczynających pracę z kodem współbieżnym jest uznanie metod statycznych za rozkazujące instancjom poszczególnych wątków. Dla przykładu gdy mamy referencję thread na wątek, możemy wywołać metody np.: thread.sleep() albo thread.yield(). Niedoświadczony programista może pomyśleć, że są to metody wywoływane na referencji thread. Podczas gdy w rzeczywistości metody te są metodami statycznymi. Wywołujemy je więc na instancji klasy w tym wypadku java.lang.thread. Działanie tych metod nie ma żadnego wpływu na egzemplarz thread. Są one zdefiniowane w taki sposób, że wywołanie 9

13 2.2. STANY WĄTKÓW ich wpływa na obecnie wywoływany wątek znajdujący się w stanie uruchomiony. Jest to dowód na to jak dobrą praktyką jest wywoływanie metod statycznych wyłącznie przez klasę a nie jej instancję i jak bardzo mylący może się okazać przeciwny przypadek. Wątek może być też zablokowany. Oznacza to, że oczekuje on na zasoby takie jak blokada na obiekcie, albo urządzenie wejścia/wyjścia. Niezależnie od przypadku, oznacza to, że wydarzeniem które powoduje przejście z powrotem do stanu uruchamialny jest dostępność zasobu. Przykładem może być zwolnienie blokady na obiekcie. Warto na zakończenie dodać, że wątek zablokowany jest uznawany za wątek żywy. W końcu wątek może być uśpiony, gdy kod uruchomieniowy wątku, każe mu wstrzymywać wykonanie na jakiś określony czas (metoda sleep()). Przejście do stanu kwalifikującego się do uruchomienia jest powodowane przez zdarzenie budzące wątek, gdy czas oczekiwania minie. Martwy (ang. dead) Wątek jest uważany za martwy, gdy wywołanie jego metody run() dobiegnie końca. W tym momencie wątek przestaje być wątkiem uruchomieniowym. Nie oznacza to jednak, że przestaje być wątkiem w sensie obiektu Javy. Kiedy wątek znajdzie się w stanie martwy, nie może już nigdy zostać przywrócony do życia nie może zmienić swojego stanu. Gdy spróbujemy wywołać metodę run() na wątku, znajdującym się w stanie martwy, nie zostanie rzucony wyjątek przy kompilacji. Zostanie natomiast rzucony wyjątek w trakcie wykonywania programu. Na zakończenie drobna, ale istotna oczywistość wątek martwy nie jest uznawany za żywy. 10

14 2.3. BEZPIECZEŃSTWO WĄTKÓW Rysunek 2.1: Stany wątków i przejścia pomiędzy nimi. 2.3 Bezpieczeństwo wątków Zdefiniowanie bezpieczeństwa wątków (ang. thread safety) jest wyjątkowo problematyczne. Idąc za tokiem rozumowania jednego z twórców obsługi wielowątkowości na platformie Javy, oraz autora książki [3], Briana Goetza: Klasa jest bezpieczna wielowątkowo, jeżeli zachowuje się poprawnie nawet gdy korzysta z niej jednocześnie wiele wątków, niezależnie od uszeregowania i przeplatania wykonań wątków poprzez środowisko uruchomieniowe, oraz bez dodatkowej synchronizacji czy innego rodzaju koordynacji po stronie kodu wywołującego tę 11

15 2.4. RÓŻNICE POMIĘDZY PROCESEM A WĄTKIEM klasę. 3 Bezstanowe obiekty są zawsze bezpieczne wielowątkowo, a wynika to z faktu, że akcje wątku korzystającego z bezstanowego obiektu nie mogą wpłynąć na poprawność operacji w innych wątkach. 2.4 Różnice pomiędzy procesem a wątkiem Proces jest definiowany jako egzemplarz wykonywanego programu. Każda aplikacja składa się z co najmniej jednego procesu. Każdy nowo powstały proces otrzymuje unikatowy numer, który go jednoznacznie identyfikuje. Numer ten oznaczany jest jako PID (ang. process identifier). Aby wykonać program system operacyjny musi przydzielić zasoby (pamięć, czas procesora, dostęp do urządzeń wejścia-wyjścia, pliki, etc.). Może się także pojawić konieczność wykonania pewnych fragmentów programu w sposób współbieżny. Aby to zrealizować, program może zażądać utworzenia określonej liczby wątków. Każdy proces jest uruchamiany z jednym wątkiem często nazywanym głównym wątkiem ale może tworzyć dodatkowe wątki. Wątki współdzielą prawie wszystkie zasoby zarezerwowane dla danego procesu. Wyjątkiem jest czas procesora, który jest przydzielany w sposób indywidualny dla każdego z wątków. Zarządzaniem procesami zajmuje się jądro systemu operacyjnego, a sam sposób obsługi jest różny dla poszczególnych systemów. W systemie operacyjnym każdy proces posiada proces nadrzędny, z kolei każdy proces może, poprzez wywołanie funkcji systemu operacyjnego, utworzyć swoje procesy potomne. W ten sposób tworzy się swego rodzaju drzewo procesów. Każdy proces otrzymuje od systemu operacyjnego odrębne zasoby, w tym odrębną przestrzeń adresową, listę otwartych plików, urządzeń itp. Wątek jest bytem w obrębie procesu który może być kolejkowany do wykonania. Wszystkie wątki w obrębie jednego procesu dzielą przestrzeń adresową oraz zasoby. Ponadto każdy wątek zarządza obsługą wyjątków, priory- 3 Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, Doug Lea Java Concurrency in Practice. Addison-Wesley Professional; wydanie pierwsze, 2006, s

16 2.5. PRZEŁĄCZANIE KONTEKSTU tetami kolejkowania, unikalnym identyfikatorem wątku, pamięcią w obrębie wątku oraz zbiorem współdzielonych między wątkami struktur, których system operacyjny będzie używać do zachowania kontekstu wątku do momentu aż zostanie on skolejkowany. 2.5 Przełączanie kontekstu Przełączanie kontekstu jest to przełączenie się w wykonywaniu procesora z jednego procesu lub wątku do innego. Można opisać to nieco bardziej dokładnie jako jądro systemu operacyjnego wykonujące następujące czynności w odniesieniu do procesów na procesorze. 1. Zawieszenie postępu prac nad jednym z procesów oraz zapisanie stanu procesora (tj. kontekstu) dot. tego procesu w pamięci, 2. Wydobycie kontekstu innego procesu z pamięci i odtworzenie go w rejestrach procesora, 3. Powrót do stanu w którym pierwotny proces został przerwany (ang. interrupted) i kontynuacja wykonywania procesu. Przełączanie kontekstu nazywane jest też potocznie przełączeniem procesów, albo przełączaniem zadań. 2.6 Model pamięciowy Javy Wirtualna maszyna Javy stara się modelować komputer uwzględniając przy tym oczywiście pamięć. Model pamięciowy Javy decyduje w jaki sposób maszyna wirtualna Javy współpracuje z pamięcią RAM komputera. Określa jak i kiedy wątki mogą widzieć wartości zapisywane do zmiennych współdzielonych oraz jak synchronizować dostęp do tych zmiennych. Model pamięciowy w pierwszych wersjach Javy był niewydajny, stąd został on przebudowany w wersji 1.5. Stworzony wtedy model obowiązuje nadal w najnowszej wersji Javy

17 2.6. MODEL PAMIĘCIOWY JAVY Sprzętowa architektura pamięci różni się od modelu pamięciowego zastosowanego na platformie Java. Sprzętowa architektura pamięci nie rozróżnia bytów takich jak sterta czy też stos wątku odpowiednikiem obydwu jest po prostu pamięć główna. Niektóre fragmenty stosów wątków oraz sterty mogą niekiedy znajdować się w pamięci podręcznej lub w rejestrach wewnętrznych procesora. Fakt, że obiekty i zmienne mogą być przechowywane w zupełnie różnych obszarach, może powodować pewne problemy. Mianowicie: niewidoczność zmian na zmiennych współdzielonych, wyścigi podczas prób odczytywania, sprawdzania czy zapisywania wartości na zmiennej współdzielonej Widoczność zmiennych współdzielonych Jeżeli co najmniej dwa wątki współdzielą ze sobą obiekt bez użycia synchronizacji, lub modyfikatora volatile, to wtedy zapis jednego z wątków do współdzielonego obiektu może nie być widoczny dla pozostałych. Wynika to ze wspomnianych różnic w modelach pamięci Javy oraz sprzętowego. Rozważony zostanie przypadek gdzie współdzielony obiekt początkowo jest przechowywany w pamięci głównej RAM, oraz działanie przeprowadzane jest na maszynie z dwoma procesorami. Wątek uruchomiony na pierwszym z procesorów wczytuje zmienną współdzieloną do pamięci podręcznej (ang. cache), gdzie dokonuje na niej zmian. Do momentu kiedy dane z pamięci podręcznej procesora nie zostaną przeniesione do pamięci głównej, zmieniona wersja współdzielonego obiektu nie jest widoczna dla wątku działającego na drugim rdzeniu. W ten sposób, może się okazać, że każdy z wątków będzie miał swoją kopię współdzielonej zmiennej każda z tych kopii w odpowiedniej pamięci podręcznej każdego z rdzeni. Poniższy obrazek 2.2 ilustruje opisywaną sytuację. Wątek uruchomiony na pierwszym z procesorów kopiuje zmienną współdzieloną do pamięci podręcznej swojego procesora i tam zmienia wartość zmiennej licznik na 2. Zmiana ta nie jest widoczna dla drugiego wątku uruchomionego na drugim 14

18 2.6. MODEL PAMIĘCIOWY JAVY procesorze, ponieważ zapis na zmiennej licznik nie został przeniesiony z pamięci podręcznej do pamięci głównej. Rysunek 2.2: Widoczność zmiennych współdzielonych. Aby rozwiązać tego typu problem należy używać słowa kluczowego volatile. Zapewnia ono, że zmienna opatrzona tym słowem kluczowym będzie zawsze bezpośrednio wczytywana z pamięci głównej RAM, jak i bezpośrednio do niej zapisywana Wyścigi Jeżeli co najmniej dwa wątki współdzielą obiekt, i co najmniej jeden wątek zapisuje do zmiennych we współdzielonym obiekcie, może wystąpić zjawisko wyścigów. Rozważmy sytuację, że wątek A wczytuje zmienną licznik współdzielonego obiektu do pamięci podręcznej jednego z procesorów. Podobnie wątek B ale do pamięci podręcznej innego procesora. Następnie wątek A inkrementuje wartość zmiennej licznik, a wątek B robi dokładnie to samo. Oznacza 15

19 2.6. MODEL PAMIĘCIOWY JAVY to, że zmienna licznik została zainkrementowana dwa razy po jednym razie z oddzielnych pamięci podręcznych procesorów. Jeżeli powyżej opisane inkrementacje wykonywałyby się w sposób sekwencyjny, to zmienna licznik zostałaby zainkrementowana dwukrotnie i w rezultacie jej wartością końcową, która znalazłaby się w pamięci głównej byłaby liczba równa początkowej wartości zmiennej licznik powiększona o 2. Jednak w analizowanym przykładzie mamy do czynienia ze środowiskiem wielowątkowym, bez poprawnej synchronizacji. Oznacza to, że niezależnie od tego czy do pamięci głównej zostanie zapisana uaktualniona wartość zmiennej licznik z wątku A, czy z wątku B, to ta zaktualizowana wartość będzie jedynie o 1 większa od wartości początkowej pomimo dwóch inkrementacji. Poniższy rysunek 2.3 obrazuje wyżej opisaną sytuację jest to sztampowy przykład wyścigu. Rysunek 2.3: Ilustracja przedstawiająca wyścig. Podstawowym sposobem na radzenie sobie z wyścigami, jest używanie synchronizacji. Bloki synchronized w języku Java gwarantują, że tylko jeden wątek może wejść do sekcji krytycznej fragmentu kodu, który wyko- 16

20 2.6. MODEL PAMIĘCIOWY JAVY rzystuje zasób współdzielony. Oprócz tego zapewniają, że wszystkie zmienne do których istnieją odwołania z poziomu sekcji krytycznej będą wczytywane z pamięci głównej, a przy wyjściu z sekcji krytycznej wszystkie zaktualizowane wartości będą zapisane do pamięci głównej niezależnie od tego czy zmienna została zadeklarowana jako volatile, czy nie Atomowość operacji Rozważona zostanie sytuacja gdy do obiektu, który wcześniej był bezstanowy, dodane zostanie pole określające stan. Typowym przykładem jest dodanie licznika wywołań np. do serwletu. W środowisku jednowątkowym oczywistym działaniem byłoby dodanie pola typu long do klasy, oraz zwiększanie jego wartości przy każdym obsłużeniu żądania. Niestety takie rozwiązanie nie jest bezpieczne wielowątkowo. Choć wydawałoby się, że niepozorna operacja inkrementacji np. counter++ jest pojedynczą akcją, to w rzeczywistości nie jest ona atomowa. Oznacza to, że nie wykonuje się jako pojedyncza, niepodzielna operacja. Zamiast tego powyższy zapis jest skrótem, który reprezentuje 3 dyskretne operacje: pobierz aktualną wartość, dodaj 1 do pobranej wartości, przypisz zmienioną wartość do pierwotnej zmiennej. Przyjmijmy teraz, że istnieją dwa wątki, które próbują inkrementować zmienną licznika i że początkowo zmienna ta ma wartość 2. Niefortunnie każdy z wątków mógłby najpierw odczytać wartość, ustalić, że jest ona równa 2, dodać do niej 1 i zmienić wartość zmiennej na 3. Nie jest to pożądane działanie, gdyż właśnie straciliśmy ślad po jednym wywołaniu. Możliwość uzyskania niepoprawnych wyników dla niefortunnego ułożenia czasowego wywołań jest w programowaniu wielowątkowym bardzo ważna i została określona mianem wyścigów. Wyścigi to niebezpieczne sytuacje, w których co najmniej dwa wątki współdzielą dane i próbują je zmienić w tym samym czasie. Szczegółowy opis znajduje się w podrozdziale

21 2.6. MODEL PAMIĘCIOWY JAVY Sytuacja opisana powyżej nazywana jest w literaturze wyścigiem typu czytaj, modyfikuj, zapisz (ang. read-modify-write). Kolejnym typem wyścigów jest sprawdź i działaj (ang. check-then-act). Występuje on wtedy, gdy przed wykonaniem akcji sprawdzana jest prawdziwość warunku np. sprawdzenie przed tworzeniem nowego pliku czy plik o podanej ścieżce i nazwie już istnieje. Niebezpieczeństwo polega na tym, że w przypadku kodu wielowątkowego w momencie po sprawdzeniu (czy plik istnieje?), ale jeszcze przed działaniem (stwórz nowy plik) inny wątek może zmienić stan np. tworząc taki sam plik o podanej nazwie i ścieżce powodując zakończenie działania programu z błędem. Można zabezpieczyć się przed wyżej wymienionymi zagrożeniami zapewniając atomowość operacji. Operacja nazywana jest atomową, gdy jest ona pojedyncza oraz niepodzielna. Sekwencje operacji, które muszą być wykonywane w sposób atomowy aby pozostać bezpiecznymi wielowątkowo to akcje połączone (ang. compund actions). Brian Goetz w książce [3] definiuje atomowość operacji następująco: Operacje A i B są atomowe względem siebie gdy z perspektywy wątku wykonującego operację A, gdy inny wątek wykonuje B, to albo zadanie wykonało się całkowicie albo wcale. 4 Java ułatwia wykonywanie operacji atomowych dostarczając pakietu java.util.concurrent.atomic. Znajdują się w nim klasy-otoczki dla typów prostych np. AtomicInteger, AtomicLong, które udostępniają metody pozwalające uniknąć opisywanych powyżej wyścigów. Np. metoda compare- AndSet() rozwiązuje problem wyścigu typu sprawdź i działaj. W przypadku typów prostych Java gwarantuje atomowość zapisu i odczytu dla zmiennych typu char, boolean, byte, short, int, float. Wyjątkiem są więc typy long i double. Powodem jest sposób zapisu tych typów. Zmienne typu long oraz double potrzebują 64 bitów pamięci, przez co JVM zapisuje takie zmienne jako dwa bloki 32-bitowe. W przypadku aplikacji wielowątkowych może to powodować absurdalne wyniki np. uzyskanie po jednym bloku 4 Ibidem s

22 2.7. MECHANIZM THREADPOOLEXECUTOR pamięci z każdego z dwóch wątków próbujących zapisać do zmiennej. Aby zabezpieczyć się przed takim efektem zagrożone zmienne należy opatrzyć modyfikatorem volatile. Zapewnia on odczyt aktualnej wartości nawet w przypadku jej zmiany w innym wątku. Nie zapewnia natomiast spójności pamięciowej, więc nie jest równoznaczny z synchronizacją. 2.7 Mechanizm ThreadPoolExecutor Klasa ThreadPoolExecutor jest typu ExecutorService. Służy ona do obsługiwania zadań poprzez ich pojedyncze wykonywanie przy pomocy wątków dostępnych w puli wątków. Pule wątków mają charakterystyczne cechy, które wpływają na wydajność implementacji. Zazwyczaj cechują się lepszą wydajnością przy wykonywaniu dużej liczby asynchronicznych zadań. Wynika to z faktu, że przy użyciu puli wątków pozbywamy się kosztów związanych z tworzeniem i niszczeniem wątków. Dodatkowo mechanizm ThreadPoolExecutor dostarcza środków pozwalających na zarządzanie wątkami oraz innymi zasobami (np. czasem) w trakcie wykonywania zadań oraz umożliwia wgląd do podstawowych statystyk zawierających dane np. o liczbie ukończonych zadań. Pula taka jest zazwyczaj tworzona przy pomocy metod wytwórczych dostępnych w klasie Executors. Instancję tej klasy można także stworzyć poprzez dostępne konstruktory. Minimalny zestaw parametrów to: corepoolsize - domyślna liczba wątków, które zawsze powinny być obecna w puli, niezależnie od tego czy mają jakieś zadania do wykonania czy nie, maximumpoolsize - maksymalna liczba wątków, która może znaleźć się w puli, keepalivetime - jeżeli liczba wątków w puli jest większa niż domyślna wartość, to parametr ten określa jak długo bezczynne wątki pozostaną w niej przed zniszczeniem, 19

23 2.8. MECHANIZM FORK/JOIN unit - jednostka czasu parametru keepalivetime, workqueue - kolejka służąca do przetrzymywania zadań przed tym jak zostaną one wykonane przez pulę. Mechanizm ThreadPoolExecutor zwalnia więc programistę z implementacji kodu zajmującego się tworzeniem oraz niszczeniem wątków. Ponadto używa jednej, konfigurowalnej kolejki zadań przetrzymujących obiekty typu Runnable oczekujące na wykonanie. Działanie takiej kolejki można zapisać w trzech punktach: żądaj następnego zadania, wykonaj je, czekaj na kolejne zadania. Poniżej rysunek ilustrujący działanie puli wątków. Rysunek 2.4: Ilustracja działania puli wątków. 2.8 Mechanizm fork/join Mechanizm fork/join to implementacja interfejsu ExecutorService, która ułatwia wykorzystanie wielu procesorów. Mechanizm ten jest zaprojektowany do pracy z problemami, które mogą być podzielone rekurencyjnie na 20

24 2.8. MECHANIZM FORK/JOIN mniejsze części. Docelowo ma on wykorzystać całą dostępną moc obliczeniową, aby zwiększyć wydajność aplikacji. Podobnie jak w przypadku każdej implementacji interfejsu Executor- Service, mechanizm fork/join dystrybuuje zadania do wątków dostępnych w puli wątków. Używanie puli wątków jest jednak spotykane w innych mechanizmach. Cechą wyróżniającą mechanizmu fork/join jest wykorzystanie algorytmu kradzieży zadań (ang. work-stealing). Polega on na tym, że w przypadku gdy wątkom dostępnym w puli wątków zabraknie zadań do wykonania, to kradną one zadania od innych wątków, które są zajęte. Zostało to zrealizowane w taki sposób, że każdy wątek w puli posiada swoją kolejkę zadań. Zadania są odpowiednio dodawane lub pobierane z kolejki przez wątek do którego taka kolejka należy. 5 Pomimo faktu, że operacja kradzieży zadań i zdejmowania zadania z kolejki działają na innych końcach kolejki, to operacja kradzieży zadania jest chroniona poprzez rygiel/blokadę (ang. lock). Ważną kwestią przy użyciu mechanizmu fork/join jest umiejętne tworzenie zadań, bowiem rozmiar zadania może znacząco wpłynąć na wydajność. Zadania, które będą za duże spowodują, że algorytm kradzieży zadań nie będzie funkcjonował poprawnie, gdyż w kolejkach poszczególnych wątków nie będzie czego podbierać. Z kolei przy zbyt małych zadaniach, koszt tworzenia nowego wątku może być wyższy niż zysk uzyskany z zastosowania zrównoleglenia. Poniższy rysunek obrazuje działanie algorytmu kradzieży zadań. W pierwszej chwili rozważane są dwa wątki, każdy z kolejką zawierającą po cztery zadania. W drugiej chwili w wyniku nierównomiernego rozkładu zadań, albo ich niejednorodnego rozmiaru Wątek 1 ma wciąż 3 zadania do wykonania, a Wątek 2 nie ma ich wcale. W momencie kiedy Wątek 2 dowiaduje się, że jego kolejka jest pusta, próbuje skraść zadania od innych wątków. W tym wypadku można mówić o jedynie jednym innym wątku. Wątek 2 zauważa, że może skraść zadanie od Wątku 1, po czym wykonuje operację kradzieży zadania (zdjęcie zadania z końca kolejki Wątku 1). To pokazuje potencjał algorytmu kradzieży zadań, ale także uświadamia jak istotny jest rozmiar zadania. Gdyby zadania były np. pięciokrotnie więk- 5 Fork/Join, w: dostęp:

25 2.9. PRAWO AMDAHLA sze, to już w drugiej chwili Wątek 2 nie miałby co robić, marnując przy tym czas procesora. Rysunek 2.5: Ilustracja działania algorytmu kradzieży zadań (ang. workstealing). 2.9 Prawo Amdahla Niektóre problemy można rozwiązywać coraz to szybciej korzystając z większej ilości zasobów im więcej jest robotników na budowie tym szybciej można wykonać pracę. Inne zadania są z natury szeregowe, a żadna liczba dodatkowych pracowników nie będzie w stanie przyspieszyć wykonania zadania choćby o milisekundę. Jeżeli chcemy wykorzystać i kontrolować w jak największym stopniu moc wielu procesorów jednocześnie, musimy się upewnić, że problem który chcemy w taki sposób rozwiązać nadaje się do zdekomponowania na wiele zadań równoległych. Ponadto należy sprawdzić, czy nasz program w pełni efektywnie wykorzystuje potencjał do zrównoleglenia. Większość programów równoległych ma wiele wspólnego z powyższą analogią do sytuacji na budowie. Składają się one bowiem z części, które doskonale nadają się do zrównoleglenia i z części szeregowych. W 1967 Gene Amdahl sformułował Prawo Amdahla, które mówi o tym jak bardzo można przyspieszyć obliczenia, gdy ich pewna część będzie wykonywana w sposób równoległy. Opiera się ono na proporcjach komponentów nadających się do zrównoleglenia do komponentów szeregowych. Jeżeli poprzez F oznaczymy ułamek prac, które muszą zostać wykonane w sposób szeregowy, to wtedy 1 F oznaczać będzie ułamek prac, które mogą zostać wykonane w sposób równoległy. Prawo Amdahla opisuje jakie przyspieszenie możemy osiągnąć 22

26 2.9. PRAWO AMDAHLA na maszynie posiadającej N procesorów wg wzoru: P rzyspieszenie 1 F + (1 F ) N Wraz ze wzrostem wartości N, maksymalne przyspieszenia zbiega się z wartością maksymalną równą 1. Wnioski nie są oczywiste i nie pokrywają F się z wyobrażeniami o bardzo dużych możliwościach przyspieszenia wraz ze zwiększeniem mocy obliczeniowej. Powyższy wzór oznacza bowiem, że w przypadku zadania w którym 50% obliczeń musi zostać wykonana w sposób sekwencyjny, może ono zostać przyspieszone maksymalnie dwukrotnie, niezależnie od tego ile maszyna ma dostępnych procesorów, a w przypadku problemu w którym 10% obliczeń musi zostać wykonana w sposób sekwencyjny współczynnik przyspieszenia może osiągnąć maksymalnie wartość 10. Prawo Amdahla pozwala także określić stopień utylizacji maszyny definiowany jako maksymalne przyspieszenie dzielone na liczbę procesorów. Mając 10 dostępnych procesorów, program zawierający 10% obliczeń możliwych do wykonania w sposób sekwencyjny może osiągnąć przyspieszenie maksymalnie rzędu 5.3 (utylizacja równa 53%). Przy dostępności 100 procesorów i takiego samego stosunku kodu sekwencyjnego do kodu równoległego maksymalne przyspieszenie będzie mogło maksymalnie osiągnąć wartość współczynnika 9.2 (utylizacja równa 9%). W praktyce oznacza to, że trudno jest i potrzeba wiele niewydajnie zutylizowanych procesorów aby nie osiągnąć współczynnika równego 10. Zgodnie z wykresem widocznym na rysunku 2.6 im większa jest liczba procesorów, tym większy wpływ na przepustowość ma kod który musi być wykonany w sposób sekwencyjny i ogranicza wzrost powodowany dodaniem zasobów w postaci dodatkowych rdzeni. Poniższe ilustracje 2.7, 2.8, oraz 2.9 pokazują wpływ dodania kolejnych zasobów do rozwiązywania problemu. Oś reprezentuje czas potrzebny na wykonanie zadania. 23

27 2.9. PRAWO AMDAHLA Rysunek 2.6: Prawo Amdahla. Rysunek 2.7: Prawo Amdahla. Wykonanie problemu na jednym procesorze. 24

28 2.10. PLANISTA WĄTKÓW Rysunek 2.8: Prawo Amdahla. Wykonanie problemu na dwóch procesorach. Rysunek 2.9: Prawo Amdahla. Wykonanie problemu na trzech procesorach Planista wątków Planista wątków (ang. thread scheduler) jest częścią wirtualnej maszyny Javy JVM (chociaż większość implementacji JVM mapuje wątki javowe do wątków natywnych na systemie operacyjnym na którym wykonywany jest kod), która decyduje który wątek zostanie uruchomiony w danym momencie, oraz który z wątków zmieni swój stan z uruchomionego na inny. 25

29 2.10. PLANISTA WĄTKÓW Rozważmy przypadek, gdzie maszyna z której korzystamy posiada 1 procesor. Oznacza to, że naraz może wykonywać się dokładnie jeden wątek tylko jeden stos. Zadaniem planisty wątków jest decydowanie o tym który z wątków zostanie uruchomiony spośród wątków, które mogą zostać w danej chwili uruchomione (są uruchamialne ang. runnable). Którykolwiek z wątków, które są uruchamialne może zostać wybrany przez planistę aby być jedynym wykonywanym wątkiem. Jeżeli wątek nie jest uruchamialny, nie może zostać wybrany przez planistę jako pretendent to bycia obecnie wykonywanym wątkiem. Istotnym jest fakt, że kolejność w której uruchamialne wątki są wybierane do uruchomienia jest nieokreślony. 6 Typowym, acz niegwarantowanym zachowaniem planisty jest imitacja kolejki. Oznacza to, że jeżeli wątek skończy lub wstrzyma wykonywanie swojego zadania, przesuwa się na koniec puli wątków uruchamialnych. Tam oczekuje momentu, aż stanie się pierwszym elementem i będzie mógł być wybrany po raz kolejny. Celowo w nomenklaturze mówi się o miejscu w puli wątków a nie w kolejce, ze względu na uwydatnienie faktu, że wątki nie są ułożone w określonej, znanej kolejności jest to zależne od maszyny wirtualnej Javy. Pomimo tego, że programista nie jest w stanie sprawować kontroli nad planistą wątków (tj. np. wskazać który wątek ma zostać wykonany jako następny), to jest w stanie wpływać na tę decyzję. Poniższe metody dają nam możliwość insynuowania planiście wątków, jaką kolejność chcielibyśmy przyjąć. Insynuacji tych nie należy jednak mylić z kontrolą. Metody z klasy java.lang.thread: public static void sleep(long millis) throws InterruptedException jest używana do tego aby spowolnić wątek. public static void yield() informuje planistę wątków o tym, że wątek może przejść w stan oczekiwania i tym samym zwolnić zasoby dla innych wątków. Metoda ta nie jest polecana przy tworzeniu nowych aplikacji wielowątkowych. 6 Kathy Sierra, Bert Bates Java SE 7 Programmer I & II Study Guide. Oracle Press; 2014, s

30 2.11. KOMUNIKACJA MIĘDZY WĄTKAMI public final void join() throws InterruptedException pozwala na to aby jeden wątek oczekiwał na ukończenie innego. public final void setpriority(int newpriority) pozwala ustawić priorytet wykonania danego wątku. Wartość ta jest traktowana jedynie jakos wskazówka, ponadto niektóre wirtualne maszyny Javy mogą normalizować te wartości. Metody z klasy java.lang.object omówione w kolejnym podrozdziale: public final void wait() throws InterruptedException public final void notify() public final void notifyall() 2.11 Komunikacja między wątkami Wątki komunikują się ze sobą wymieniając między sobą różne informacje np. informacje o statusie zablokowania. W języku Java klasa java.lang.- Object posiada 3 metody, które ułatwiają wątkom sygnalizowanie stanów które mogą być dla innych wątków interesujące. Są to metody: wait(), notify() oraz notifyall(). Rozważmy przypadek, gdzie mamy do czynienia z dwoma wątkami. Jeden zajmuje się odbiorem wiadomości, a drugi zajmuje się ich przetwarzaniem. W takiej sytuacji wątek zajmujący się przetwarzaniem musi co jakiś czas sprawdzać, czy są jakieś wiadomości do przetworzenia. Mechanizmy wait oraz notify pozwalają na to, żeby wątek zajmujący się przetwarzaniem, w przypadku gdy nie ma dla niego żadnych wiadomości do przetworzenia, mógł przejść w stan oczekiwania. Stan ten trwa aż do momentu kiedy inny wątek poinformuje, że jest powód, żeby zmienić stan z oczekiwania do stanu działania. Należy zwrócić uwagę na fakt, że metody wait(), notify() oraz notify- All() mogą być wywoływane jedynie z obrębu bloku synchronized. In- 27

31 2.11. KOMUNIKACJA MIĘDZY WĄTKAMI nymi słowy wątek nie może wywołać metod wait() czy notify() na obiekcie, jeżeli nie posiada na nim blokady. Działanie metod wait() oraz notify() omówię na przykładzie inspirowanym pozycją [1]. 7 Użytkownik chce wydrukować kształty na drukarce 3D. Ma do swojej dyspozycji urządzenie zdolne do drukowania 3D, oraz aplikację która pozwala mu wybrać kształt do wydrukowania. Poniżej widoczny jest pseudokod dla opisanej sytuacji. public void run() { // Uzytkownik wybiera ksztalt do druku // Aplikacja oblicza instrukcje dla drukarki // Aplikacja wysyla wyliczone kroki postepowania dla drukarki } Rozwiązanie takie nie jest wydajne. W trakcie drukowania przez drukarki określonego kształtu, użytkownik nie może wykonywać żadnych działań w szczególności nie może komunikować się z aplikacją, aby wskazać kolejny kształt do wydrukowania. Intuicyjnym rozwiązaniem byłoby rozdzielenie powyższego procesu na wątki. Jeden z nich byłby odpowiedzialny za komunikację z użytkownikiem, a drugi zajmowałby się zarządzaniem sprzętem. Wątek odpowiedzialny za komunikację z użytkownikiem musi przekazywać informacje dotyczące wyboru użytkownika wątkowi odpowiedzialnemu za komunikację z maszyną, po czym wracać do swojego zadania nasłuchiwania na działania użytkownika. Po otrzymaniu instrukcji od wątku użytkownika, wątek drukarki zaczyna wykonywać otrzymane kroki. Obydwa wątki używają do komunikacji wspólnego obiektu, który przetrzymuje informacje o kształcie, który w danym momencie jest przetwarzany. public void petlauzytkownika() { // Wczytaj wybrany przez uzytkownika ksztalt // Wyznacz kroki potrzebne drukarce do wydrukowania tego ksztaltu w 3D 7 Kathy Sierra, Bert Bates Java SE 7 Programmer I & II Study Guide. Oracle Press; 2014, s

32 2.11. KOMUNIKACJA MIĘDZY WĄTKAMI } // Zapisz wyznaczone kroki we wspolnym obiekcie public void petladrukarki() { while (true) { // Pobierz kroki dzialania ze wspolnego obiektu // Przekaz kroki dzialania urzadzeniu } } Skoro mamy już wyznaczony szkic rozwiązania, teraz należy opracować sposób na to aby wątek drukarki zaczął przetwarzać kroki działania dla urządzenia tak szybko jak to tylko jest możliwe. Z kolei wątek użytkownika nie powinien tych kroków zmieniać dopóki nie zostaną w całości przesłane do wątku drukarki. Rozwiązaniem dla tego typu problemów może być właśnie metoda wait() oraz notify() a także synchronizacja kodu. Każdy obiekt w języku Java ma swoją blokadę (ang. lock). Podobnie każdy obiekt może mieć listę wątków, które oczekują na powiadomienie z tego obiektu. Aby dostać się na tę listę wątek musi wykonać metodę wait() na docelowym obiekcie. Od tej chwili, wątek nie wykona żadnej instrukcji aż do momentu, gdy zostanie wywołana na obiekcie docelowym metoda notify(). W przypadku gdy wiele wątków oczekuje na powiadomienie z docelowego obiektu, zostanie wybrany tylko i wyłącznie jeden z nich kolejność nie jest gwarantowana i będzie mógł kontynuować swoje działanie. Jeżeli nie ma żadnych wątków oczekujących na powiadomienie, to wtedy wywołanie metody notify() nie ma żadnych skutków nic się nie dzieje. Aby zastosować powyżej opisane metody w przypadku hipotetycznego problemu drukowania 3D należy sprawić aby wątek drukarki oczekiwał na dostępność kroków działania, a wątek użytkownika wysyłał powiadomienie tuż po ich wyznaczeniu. W rezultacie kod mógłby wyglądać jak poniżej: class Uzytkownik extends Thread { public void run() { while (true) { 29

33 2.11. KOMUNIKACJA MIĘDZY WĄTKAMI } } } // Pobierz ksztalt od uzytkownika synchronized(this) { // Wyznacz kroki dzialania dla drukarki notify(); } class Drukarka extends Thread { Uzytkownik uzytkownik; // zakladamy, ze ten obiekt jest inicjalizowany public void run() { while(true) { synchronized(uzytkownik) { try { uzytkownik.wait() } catch(interruptedexception ie) { // Przekaz kroki dzialania do drukarki } } } } } Tuż po uruchomieniu, wątek drukarki przechodzi w stan oczekiwania. Oczekiwanie będzie trwało dopóki wątek użytkownika wyśle pierwsze powiadomienie. W tym momencie, to wątek użytkownika trzyma blokadę na obiekcie, a więc wątek drukarki jest bezczynny. Dopiero po tym jak wątek użytkownika porzuca blok synchronized, wątek drukarki może zacząć przetwarzać przekazane kroki działania. Podczas gdy jeden kształt jest przetwarzany poprzez drukarkę, użytkownik nadal może komunikować się z systemem i np. wskazać kolejny kształt do wydrukowania w 3D. Kiedy użytkownik wybierze kształt do wydrukowania, 30

34 2.11. KOMUNIKACJA MIĘDZY WĄTKAMI wątek użytkownika podejmuje próbę wejścia do bloku synchronized, możliwe, że poprzez zablokowanie dopóki wątek drukarki dokończy wszystkie przetwarzane kroki działania potrzebne do wydrukowania konkretnego kształtu. Kiedy wątek drukarki ukończy swoją pracę, powtarza pracę w pętli, przechodząc do stanu oczekiwania jednocześnie zwalniając blokadę na obiekcie. Dopiero wtedy wątek użytkownika może wejść do bloku synchronized i nadpisać kroki działania dla drukarki nowymi na podstawie kolejnego wyboru użytkownika. Rozdzielenie pracy na dwa wątki daje niewątpliwe zyski w porównaniu do wykonywania tych samych działań na tylko jednym wątku, choć w przypadku tej implementacji, nadal istnieje możliwość tego, że użytkownik będzie musiał czekać. Kolejną poprawką byłoby wprowadzenie kolejki do której byłyby dokładane kolejne kształty do wydrukowania. Wprowadzenie kolejki zmniejszyłoby prawdopodobieństwo tego, że użytkownik będzie musiał oczekiwać na drukarkę. Ponadto, jest jeszcze druga forma metody wait(). Forma ta akceptuje liczbę milisekund jako maksymalny czas do oczekiwania. Jeżeli wątek nie zostanie przerwany, będzie kontynuował pracę w sposób normalny, jeżeli dostanie powiadomienie spowodowane wywołaniem metody notify() albo czas określony w argumencie metody wait() minie. Na tę normalną kontynuację pracy wątku składa się opuszczenie stanu oczekiwania. Natomiast, aby kontynuować wykonanie, wątek musi najpierw dostać blokadę na obiekcie. synchronized(a){ // Watek dostaje blokade na obiekcie a a.wait(2000); // Watek opuszcza blokade i czeka na powiadomienie // ale tylko w przeciagu maksymalnie dwoch sekund // po czym znowu wraca do stanu "uruchamialny" // Watek pownownie dostaje blokade na obiekcie a // i wykonuje dalsze instrukcje } W większości przypadków chcemy jednak wysyłać powiadomienia do wszystkich wątków oczekujących na dany obiekt. Z pomocą przychodzi wtedy metoda notifyall() powoduje ona przejście wszystkich oczekujących wątków 31

35 2.11. KOMUNIKACJA MIĘDZY WĄTKAMI ze stanu oczekujący do stanu uruchamialny. Po wywołaniu metody notifyall() każdy z oczekujących wątków zaczyna konkurować o zdobycie blokady na wątku. W momencie kiedy każdy z oczekujących wątków dostał już blokadę na obiekcie i zwolnił ją, każdy z wątków może kontynuować swoją pracę bez konieczności dodatkowych powiadomień. 32

36 Rozdział 3 Omówienie przypadków testowych w wersji podstawowej W tym rozdziale zostaną omówione problemy w wersji sekwencyjnej które zostały zrównoleglone i poddane analizie (w kolejnym rozdziale). 3.1 Sortowanie przez scalanie mergesort Algorytm sortowania przez scalanie (ang. merge sort) to algorytm sortujący bazujący na porównaniu poszczególnych elementów. Jest to jeden z najbardziej znanych i opisywanych algorytmów typu dziel i zwyciężaj (ang. divide-and-conquer). Algorytm ten jest algorytmem rekurencyjnym. Oznacza to, że w celu rozwiązania problemu wywołuje on sam siebie (jeden lub więcej razy) przy rozwiązywaniu podobnych podproblemów. 33

37 3.1. SORTOWANIE PRZEZ SCALANIE MERGESORT Podejście dziel i zwyciężaj na każdym poziomie rekursji można podzielić na trzy etapy 1 : Dziel Zwyciężaj Połącz Problem zostaje podzielony na podproblemy będące mniejszymi egzemplarzami tego samego problemu. Podproblemy są rozwiązywane w sposób rekurencyjny, natomiast w przypadku gdy ich rozmiary są dostatecznie małe, to rozwiązywane są bezpośrednio. Rozwiązania podproblemów są łączone w rozwiązanie pierwotnego problemu. W przypadku algorytmu sortowania przez scalanie strategia ta sprowadza się do podziału wejściowego zbioru danych na połowy, a następnie posortowaniu połówek w sposób rekurencyjny. Podział jest przeprowadzany aż do momentu, gdy mamy do czynienia z jednym elementem. Następnie ów pojedynczy element jest łączony oraz sortowany wraz z elementami drugiej połowy danych, która może być zbiorem jedno lub dwuelementowym. Wynik takiego działania jest następnie łączony i sortowany z odpowiadającym wynikiem drugiej połowy i jej podzbiorów. Proces jest powtarzany aż do momentu osiągnięcia wyniku dla pierwotnego problemu. Aby skonkretyzować podejście dziel i zwyciężaj w kontekście algorytmu sortowania przez scalanie, możemy zapisać 2 Dziel Zwyciężaj N-elementowy ciąg wejściowy jest dzielony na dwie podkokolekcje po n/2 elementów każda. Otrzymane podciągi są sortowane rekurencyjnie. 1 Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein Wprowadzenie do algorytmów. Wydawnictwo PWN; wydanie trzecie, 2012, s Ibidem, s

38 3.2. SORTOWANIE SZYBKIE QUICKSORT Połącz Posortowane podciągi są łączone w jeden posortowany ciąg. Złożoność czasowa tego algorytmu to O(n log n). Sortowanie przez scalanie można zapisać w pseudokodzie jako: Wejście : Kolekcja A o rozmiarze r + 1 Wyjście: Kolekcja A z posortowanymi elementami SORTOWANIE PRZEZ SCALANIE(A, p, r): if p < r then q = (p + r)/2 SORTOWANIE PRZEZ SCALANIE(A, p, q) SORTOWANIE PRZEZ SCALANIE(A, q + 1, r) SCALANIE(A, p, q, r) end Algorytm 1: Sortowanie przez scalanie 3.2 Sortowanie szybkie quicksort Sortowanie szybkie (ang. quicksort), podobnie jak sortowanie przez scalanie, należy do grupy algorytmów z rodziny dziel i zwyciężaj. Algorytm zdefiniował w 1962 Sir Charles Antony Richard Hoare. Kroki algorytmu można zapisać koncepcyjnie jako 3 : Dziel Zwyciężaj Kolekcja wejściowa A[p..r] jest dzielona poprzez przestawianie elementów na dwie (być może puste) podkolekcje A[p..q 1] i A[q + 1..r]. Ponadto spełniona jest zależność, że element A[p..q 1] jest nie większy niż element A[q], który z kolei jest nie większy niż każdy element A[q + 1..r]. Indeks q jest obliczany jako część tej procedury podziału. Podkolekcje A[p..q 1] oraz A[q + 1..r] są rozwiązywane rekurencyjnie poprzez wywołania algorytmu sortowania szybkiego. 3 Ibidem, s

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1 Współbieżność i równoległość w środowiskach obiektowych Krzysztof Banaś Obliczenia równoległe 1 Java Model współbieżności Javy opiera się na realizacji szeregu omawianych dotychczas elementów: zarządzanie

Bardziej szczegółowo

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego Wątki Wątek - definicja Ciąg instrukcji (podprogram) który może być wykonywane współbieżnie (równolegle) z innymi programami, Wątki działają w ramach tego samego procesu Współdzielą dane (mogą operować

Bardziej szczegółowo

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1 Wątki 1. Wątki - wprowadzenie Wątkiem nazywamy sekwencyjny przepływ sterowania w procesie, który wykonuje dany program np. odczytywanie i zapisywanie plików Program Javy jest wykonywany w obrębie jednego

Bardziej szczegółowo

Wątki w Javie. Piotr Tokarski

Wątki w Javie. Piotr Tokarski Wątki w Javie Piotr Tokarski Wprowadzenie Co to są wątki? Co to są wątki? Każdy program ma przynajmniej jeden wątek Co to są wątki? Każdy program ma przynajmniej jeden wątek Wątki są po to, by symulować

Bardziej szczegółowo

Stworzenie klasy nie jest równoznaczne z wykorzystaniem wielowątkowości. Uzyskuje się ją dopiero poprzez inicjalizację wątku.

Stworzenie klasy nie jest równoznaczne z wykorzystaniem wielowątkowości. Uzyskuje się ją dopiero poprzez inicjalizację wątku. Laboratorium 7 Wstęp Jednym z podstawowych własności Javy jest wielowątkowość. Wiąże się to z możliwością współbieżnego wykonywania różnych operacji w ramach pojedynczej wirtualnej maszyny Javy (JVM).

Bardziej szczegółowo

Współbieżność w środowisku Java

Współbieżność w środowisku Java Współbieżność w środowisku Java Wątki i ich synchronizacja Zagadnienia Tworzenie wątków Stany wątków i ich zmiana Demony Synchronizacja wątków wzajemne wykluczanie oczekiwanie na zmiennych warunkowych

Bardziej szczegółowo

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ Procesy i wątki Proces posiada samodzielne środowisko wykonawcze. Proces posiada własny zestaw podstawowych zasobów w czasie wykonywania; W szczególności, każdy proces ma własną przestrzeń pamięci. W uproszczeniu

Bardziej szczegółowo

4. Procesy pojęcia podstawowe

4. Procesy pojęcia podstawowe 4. Procesy pojęcia podstawowe 4.1 Czym jest proces? Proces jest czymś innym niż program. Program jest zapisem algorytmu wraz ze strukturami danych na których algorytm ten operuje. Algorytm zapisany bywa

Bardziej szczegółowo

Programowanie współbieżne Wykład 2. Iwona Kochańska

Programowanie współbieżne Wykład 2. Iwona Kochańska Programowanie współbieżne Wykład 2 Iwona Kochańska Miary skalowalności algorytmu równoległego Przyspieszenie Stały rozmiar danych N T(1) - czas obliczeń dla najlepszego algorytmu sekwencyjnego T(p) - czas

Bardziej szczegółowo

Aplikacje w Javie- wykład 11 Wątki-podstawy

Aplikacje w Javie- wykład 11 Wątki-podstawy 1 Aplikacje w Javie- wykład 11 Wątki-podstawy Treści prezentowane w wykładzie zostały oparte o: Barteczko, JAVA Programowanie praktyczne od podstaw, PWN, 2014 http://docs.oracle.com/javase/8/docs/ http://docs.oracle.com/javase/9/docs/

Bardziej szczegółowo

4. Procesy pojęcia podstawowe

4. Procesy pojęcia podstawowe 4. Procesy pojęcia podstawowe 4.1 Czym jest proces? Proces jest czymś innym niż program. Program jest zapisem algorytmu wraz ze strukturami danych na których algorytm ten operuje. Algorytm zapisany bywa

Bardziej szczegółowo

Programowanie współbieżne i rozproszone

Programowanie współbieżne i rozproszone Programowanie współbieżne i rozproszone WYKŁAD 1 dr inż. Literatura ogólna Ben-Ari, M.: Podstawy programowania współbieżnego i rozproszonego. Wydawnictwa Naukowo-Techniczne, Warszawa, 2009. Czech, Z.J:

Bardziej szczegółowo

Kurs programowania. Wykład 8. Wojciech Macyna

Kurs programowania. Wykład 8. Wojciech Macyna Wykład 8 Program bez watków, jeden procesor, trzy zadania Program z watkami, jeden procesor, trzy zadania Procesory wielordzeniowe, każde zadanie na osobnym procesorze Trzy zadania uruchomione w watkach

Bardziej szczegółowo

Programowanie równoległe i rozproszone. W1. Wielowątkowość. Krzysztof Banaś Programowanie równoległe i rozproszone 1

Programowanie równoległe i rozproszone. W1. Wielowątkowość. Krzysztof Banaś Programowanie równoległe i rozproszone 1 Programowanie równoległe i rozproszone W1. Wielowątkowość Krzysztof Banaś Programowanie równoległe i rozproszone 1 Problemy współbieżności wyścig (race condition) synchronizacja realizowana sprzętowo (np.

Bardziej szczegółowo

Wielowątkowość. Programowanie w środowisku rozproszonym. Wykład 1.

Wielowątkowość. Programowanie w środowisku rozproszonym. Wykład 1. 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)

Bardziej szczegółowo

Programowanie komputerów

Programowanie komputerów Programowanie komputerów Wykład 7: Programowanie wielowątkowe w Javie dr inż. Walery Susłow Współbieżność Programy współbieżne (concurrent software) aplikacje potrafiące wykonywać kilka operacji w tym

Bardziej szczegółowo

Obliczenia równoległe i rozproszone w JAVIE. Michał Kozłowski 30 listopada 2003

Obliczenia równoległe i rozproszone w JAVIE. Michał Kozłowski 30 listopada 2003 Obliczenia równoległe i rozproszone w JAVIE Michał Kozłowski 30 listopada 2003 Wątki w JAVIE Reprezentacja wątków jako obiektów Uruchamianie i zatrzymywanie wątków Realizacja wątków Ograniczenia Mechanizmy

Bardziej szczegółowo

1 Wątki 1. 2 Tworzenie wątków 1. 3 Synchronizacja 3. 4 Dodatki 3. 5 Algorytmy sortowania 4

1 Wątki 1. 2 Tworzenie wątków 1. 3 Synchronizacja 3. 4 Dodatki 3. 5 Algorytmy sortowania 4 Spis treści 1 Wątki 1 2 Tworzenie wątków 1 3 Synchronizacja 3 4 Dodatki 3 5 Algorytmy sortowania 4 6 Klasa Runnable 4 Temat: Wątki Czym są wątki. Grafika. Proste animacje. Małe podsumowanie materiału.

Bardziej szczegółowo

Język Java wątki (streszczenie)

Język Java wątki (streszczenie) Programowanie współbieżna Język Java wątki (streszczenie) Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej pawel.rogalinski @ pwr.wroc.pl Języka Java wątki Autor:

Bardziej szczegółowo

Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 Uruchomienie programu powoduje stworzenie nowego procesu przez system operacyjny. Proces wykonywany program wraz

Bardziej szczegółowo

Programowanie wielowątkowe. Tomasz Borzyszkowski

Programowanie wielowątkowe. Tomasz Borzyszkowski Programowanie wielowątkowe Tomasz Borzyszkowski Wątki a procesy Jako jeden z niewielu języków programowania Java udostępnia użytkownikowi mechanizmy wspierające programowanie wielowątkowe. Program wielowątkowy

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Laboratorium 1. Wstęp do programowania w języku Java. Narzędzia 1. Aby móc tworzyć programy w języku Java, potrzebny jest zestaw narzędzi Java Development Kit, który można ściągnąć

Bardziej szczegółowo

Kurs programowania. Wykład 8. Wojciech Macyna. 10 maj 2017

Kurs programowania. Wykład 8. Wojciech Macyna. 10 maj 2017 Wykład 8 10 maj 2017 Współbieżność Watki w JAVA-ie Współbieżność może być realizowana na poziomie systemu operacyjnego (procesy) lub na poziomie aplikacji (watki). W JAVA-ie powszechnie stosuje się watki.

Bardziej szczegółowo

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1 Współbieżność i równoległość w środowiskach obiektowych Krzysztof Banaś Obliczenia równoległe 1 Java Model współbieżności Javy opiera się na realizacji szeregu omawianych dotychczas elementów: zarządzanie

Bardziej szczegółowo

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu. Zrozumienie funkcji danych statycznych jest podstawą programowania obiektowego. W niniejszym artykule opiszę zasadę tworzenia klas statycznych w C#. Oprócz tego dowiesz się czym są statyczne pola i metody

Bardziej szczegółowo

Wstęp do programowania 2

Wstęp do programowania 2 Wstęp do programowania 2 wykład 10 Zadania Agata Półrola Wydział Matematyki UŁ 2005/2006 http://www.math.uni.lodz.pl/~polrola Współbieżność dotychczasowe programy wykonywały akcje sekwencyjnie Ada umożliwia

Bardziej szczegółowo

Programowanie równoległe i rozproszone. Monitory i zmienne warunku. Krzysztof Banaś Programowanie równoległe i rozproszone 1

Programowanie równoległe i rozproszone. Monitory i zmienne warunku. Krzysztof Banaś Programowanie równoległe i rozproszone 1 Programowanie równoległe i rozproszone Monitory i zmienne warunku Krzysztof Banaś Programowanie równoległe i rozproszone 1 Problemy współbieżności Problem producentów i konsumentów: jedna grupa procesów

Bardziej szczegółowo

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1 Podstawy programowania. Wykład Funkcje Krzysztof Banaś Podstawy programowania 1 Programowanie proceduralne Pojęcie procedury (funkcji) programowanie proceduralne realizacja określonego zadania specyfikacja

Bardziej szczegółowo

Sortowanie przez scalanie

Sortowanie przez scalanie Sortowanie przez scalanie Wykład 2 12 marca 2019 (Wykład 2) Sortowanie przez scalanie 12 marca 2019 1 / 17 Outline 1 Metoda dziel i zwyciężaj 2 Scalanie Niezmiennik pętli - poprawność algorytmu 3 Sortowanie

Bardziej szczegółowo

Strategia "dziel i zwyciężaj"

Strategia dziel i zwyciężaj Strategia "dziel i zwyciężaj" W tej metodzie problem dzielony jest na kilka mniejszych podproblemów podobnych do początkowego problemu. Problemy te rozwiązywane są rekurencyjnie, a następnie rozwiązania

Bardziej szczegółowo

Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run().

Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run(). Wątki Streszczenie Celem wykładu jest wprowadzenie do obsługi wątków w Javie. Czas wykładu 45 minut. Definiowanie wątków jako klas potomnych Thread Nadpisanie metody run(). class Watek extends Thread public

Bardziej szczegółowo

4. Procesy pojęcia podstawowe

4. Procesy pojęcia podstawowe 4. Procesy pojęcia podstawowe 4.1 Czym jest proces? Proces jest czymś innym niż program. Program jest zapisem algorytmu wraz ze strukturami danych na których algorytm ten operuje. Algorytm zapisany bywa

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Laboratorium z przedmiotu Programowanie obiektowe - zestaw 02 Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami projektowania oraz implementacji klas i obiektów z wykorzystaniem dziedziczenia.

Bardziej szczegółowo

WIELOWĄTKOWOŚĆ. Waldemar Korłub. Platformy Technologiczne KASK ETI Politechnika Gdańska

WIELOWĄTKOWOŚĆ. Waldemar Korłub. Platformy Technologiczne KASK ETI Politechnika Gdańska WIELOWĄTKOWOŚĆ Waldemar Korłub Platformy Technologiczne KASK ETI Politechnika Gdańska Wydajność 2 Do 2005 roku wydajność komputerów poprawiano zwiększając częstotliwość taktowania procesora 1995: Pentium

Bardziej szczegółowo

Matematyczne Podstawy Informatyki

Matematyczne Podstawy Informatyki Matematyczne Podstawy Informatyki dr inż. Andrzej Grosser Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska Rok akademicki 2013/2014 Algorytm 1. Termin algorytm jest używany w informatyce

Bardziej szczegółowo

Współbieżność w Javie

Współbieżność w Javie Wielowątkowość (obsługa wątków) Tworzenie wątków Stany wątków i ich zmiana Demony Grupy wątków Synchronizacja wątków wzajemne wykluczanie oczekiwanie na zmiennych warunkowych pakiet java.util.concurrent

Bardziej szczegółowo

Programowanie współbieżne Wykład 10 Synchronizacja dostępu do współdzielonych zasobów. Iwona Kochańska

Programowanie współbieżne Wykład 10 Synchronizacja dostępu do współdzielonych zasobów. Iwona Kochańska Programowanie współbieżne Wykład 10 Synchronizacja dostępu do współdzielonych zasobów Iwona Kochańska Mechanizm synchronizacji wątków/procesów Wykorzystanie semaforów zapobiega niedozwolonemu wykonaniu

Bardziej szczegółowo

1. Liczby i w zapisie zmiennoprzecinkowym przedstawia się następująco

1. Liczby i w zapisie zmiennoprzecinkowym przedstawia się następująco 1. Liczby 3456.0012 i 0.000076235 w zapisie zmiennoprzecinkowym przedstawia się następująco a) 0.34560012 10 4 i 0.76235 10 4 b) 3.4560012 10 3 i 7.6235 10 5 c) 3.4560012 10 3 i 7.6235 10 5 d) po prostu

Bardziej szczegółowo

Klasy abstrakcyjne i interfejsy

Klasy abstrakcyjne i interfejsy Klasy abstrakcyjne i interfejsy Streszczenie Celem wykładu jest omówienie klas abstrakcyjnych i interfejsów w Javie. Czas wykładu 45 minut. Rozwiązanie w miarę standardowego zadania matematycznego (i nie

Bardziej szczegółowo

Algorytm. a programowanie -

Algorytm. a programowanie - Algorytm a programowanie - Program komputerowy: Program komputerowy można rozumieć jako: kod źródłowy - program komputerowy zapisany w pewnym języku programowania, zestaw poszczególnych instrukcji, plik

Bardziej szczegółowo

Projektowanie oprogramowania systemów PROCESY I ZARZĄDZANIE PROCESAMI

Projektowanie oprogramowania systemów PROCESY I ZARZĄDZANIE PROCESAMI Projektowanie oprogramowania systemów PROCESY I ZARZĄDZANIE PROCESAMI plan Cechy, właściwości procesów Multitasking Scheduling Fork czym jest proces? Działającą instancją programu Program jest kolekcją

Bardziej szczegółowo

Wykład 8: klasy cz. 4

Wykład 8: klasy cz. 4 Programowanie obiektowe Wykład 8: klasy cz. 4 Dynamiczne tworzenie obiektów klas Składniki statyczne klas Konstruktor i destruktory c.d. 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD

Bardziej szczegółowo

Task Parallel Library

Task Parallel Library Task Parallel Library Daan Leijen, Wolfram Schulte, and Sebastian Burckhardt prezentacja Michał Albrycht Agenda O potrzebie zrównoleglania Przykłady użycia TPL Tasks and Replicable Tasks Rozdzielanie zadań

Bardziej szczegółowo

Struktura i funkcjonowanie komputera pamięć komputerowa, hierarchia pamięci pamięć podręczna. System operacyjny. Zarządzanie procesami

Struktura i funkcjonowanie komputera pamięć komputerowa, hierarchia pamięci pamięć podręczna. System operacyjny. Zarządzanie procesami Rok akademicki 2015/2016, Wykład nr 6 2/21 Plan wykładu nr 6 Informatyka 1 Politechnika Białostocka - Wydział Elektryczny Elektrotechnika, semestr II, studia niestacjonarne I stopnia Rok akademicki 2015/2016

Bardziej szczegółowo

Sortowanie - wybrane algorytmy

Sortowanie - wybrane algorytmy Sortowanie - wybrane algorytmy Aleksandra Wilkowska Wydział Matematyki - Katedra Matematyki Stosowanej Politechika Wrocławska 2 maja 2018 1 / 39 Plan prezentacji Złożoność obliczeniowa Sortowanie bąbelkowe

Bardziej szczegółowo

Współbieżność w Javie

Współbieżność w Javie Wielowątkowość (obsługa wątków) Tworzenie wątków Stany wątków i ich zmiana Demony Grupy wątków Synchronizacja wątków wzajemne wykluczanie oczekiwanie na zmiennych warunkowych pakiet java.util.concurrent

Bardziej szczegółowo

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji.

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji. JAVA Java jest wszechstronnym językiem programowania, zorientowanym obiektowo, dostarczającym możliwość uruchamiania apletów oraz samodzielnych aplikacji. Java nie jest typowym kompilatorem. Źródłowy kod

Bardziej szczegółowo

Programowanie współbieżne Laboratorium nr 12

Programowanie współbieżne Laboratorium nr 12 Programowanie współbieżne Laboratorium nr 12 Uwaga!!! Wyniki uruchomionych programów mogą zależeć od sprzętu (ilość procesorów, rdzeni itp.), systemu operacyjnego, obciążenia systemu operacyjnego, ilości

Bardziej szczegółowo

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki Dariusz Brzeziński Politechnika Poznańska, Instytut Informatyki zaprojektowany jako rozszerzenie języka C o obiektowe mechanizmy abstrakcji danych jest to język pozwalający na programowanie zarówno proceduralne

Bardziej szczegółowo

Podstawy współbieżności

Podstawy współbieżności Podstawy współbieżności Algorytmy i struktury danych. Wykład 6. Rok akademicki: 2010/2011 Od koncepcji współbieżności do systemów rozproszonych Współbieżnośd rozważany na poziomie koncepcyjnym sposób realizacji

Bardziej szczegółowo

Język Java wątki (streszczenie)

Język Java wątki (streszczenie) Programowanie współbieŝna Język Java wątki (streszczenie) Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej pawel.rogalinski @ pwr.wroc.pl Podstawowe pojęcia: procesy

Bardziej szczegółowo

Model pamięci. Rafał Skinderowicz

Model pamięci. Rafał Skinderowicz Model pamięci Rafał Skinderowicz Czym jest model pamięci Model pamięci dotyczy programów współbieżnych W programie współbieżnym może się zdarzyć, że dany wątek nie będzie widział od razu wartości zmiennej

Bardziej szczegółowo

Języki i techniki programowania Ćwiczenia 2

Języki i techniki programowania Ćwiczenia 2 Języki i techniki programowania Ćwiczenia 2 Autor: Marcin Orchel Spis treści: Język C++... 5 Przekazywanie parametrów do funkcji... 5 Przekazywanie parametrów w Javie.... 5 Przekazywanie parametrów w c++...

Bardziej szczegółowo

Multimedia JAVA. Historia

Multimedia JAVA. Historia Multimedia JAVA mgr inż. Piotr Odya piotrod@sound.eti.pg.gda.pl Historia 1990 rozpoczęcie prac nad nowym systemem operacyjnym w firmie SUN, do jego tworzenia postanowiono wykorzystać nowy język programowania

Bardziej szczegółowo

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak Java język programowania obiektowego Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak 1 Język Java Język Java powstał w roku 1995 w firmie SUN Microsystems Java jest językiem: wysokiego

Bardziej szczegółowo

Zadanie polega na stworzeniu bazy danych w pamięci zapewniającej efektywny dostęp do danych baza osób.

Zadanie polega na stworzeniu bazy danych w pamięci zapewniającej efektywny dostęp do danych baza osób. Zadanie: Zadanie polega na stworzeniu bazy danych w pamięci zapewniającej efektywny dostęp do danych baza osób. Na kolejnych zajęciach projekt będzie rozwijana i uzupełniana o kolejne elementy omawiane

Bardziej szczegółowo

Procesy i wątki. Krzysztof Banaś Obliczenia równoległe 1

Procesy i wątki. Krzysztof Banaś Obliczenia równoległe 1 Procesy i wątki Krzysztof Banaś Obliczenia równoległe 1 Procesy i wątki Proces: ciąg rozkazów (wątek główny) i ewentualnie inne wątki stos (wątku głównego) przestrzeń adresowa dodatkowe elementy tworzące

Bardziej szczegółowo

Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację.

Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację. J. Ułasiewicz Programowanie aplikacji współbieżnych 1 11 11.1 abstrakcyjne Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post

Bardziej szczegółowo

Równoległość i współbieżność

Równoległość i współbieżność Równoległość i współbieżność Wykonanie sekwencyjne. Poszczególne akcje procesu są wykonywane jedna po drugiej. Dokładniej: kolejna akcja rozpoczyna się po całkowitym zakończeniu poprzedniej. Praca współbieżna

Bardziej szczegółowo

Równoległość i współbieżność

Równoległość i współbieżność Równoległość i współbieżność Wykonanie sekwencyjne. Poszczególne akcje procesu są wykonywane jedna po drugiej. Dokładniej: kolejna akcja rozpoczyna się po całkowitym zakończeniu poprzedniej. Praca współbieżna

Bardziej szczegółowo

Interfejsy w Java. Przetwarzanie równoległe. Wątki.

Interfejsy w Java. Przetwarzanie równoległe. Wątki. Informatyka I Interfejsy w Java. Przetwarzanie równoległe. Wątki. dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2017 Interfejsy w Java Pojęcie interfejsu w programowaniu Deklaracja

Bardziej szczegółowo

Wprowadzenie do programowania współbieżnego

Wprowadzenie do programowania współbieżnego Wprowadzenie do programowania współbieżnego Marcin Engel Instytut Informatyki Uniwersytet Warszawski Zamiast wstępu... Zamiast wstępu... Możliwość wykonywania wielu akcji jednocześnie może ułatwić tworzenie

Bardziej szczegółowo

Platformy Programistyczne Zagadnienia sieciowe i wątki

Platformy Programistyczne Zagadnienia sieciowe i wątki Platformy Programistyczne Zagadnienia sieciowe i wątki Agata Migalska 27/28 maja 2014 Komunikacja sieciowa 1 Komunikacja sieciowa 2 Wiele wątków 3 Serializacja Architektura typu klient-serwer Architektura

Bardziej szczegółowo

dr inż. Jarosław Forenc

dr inż. Jarosław Forenc Informatyka 2 Politechnika Białostocka - Wydział Elektryczny Elektrotechnika, semestr III, studia stacjonarne I stopnia Rok akademicki 2010/2011 Wykład nr 7 (24.01.2011) dr inż. Jarosław Forenc Rok akademicki

Bardziej szczegółowo

Zaawansowane programowanie w C++ (PCP)

Zaawansowane programowanie w C++ (PCP) Wykład 10 - boost Thread. 8 czerwca 2007 Równoległość bardzo wolna reakcja człowieka wolne urządzenia wejścia - wyjścia (np. drukarki) bardzo szybkie procesory można przeprowadzać obliczenia podczas obsługi

Bardziej szczegółowo

Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację.

Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację. J. Ułasiewicz Programowanie aplikacji współbieżnych 1 11 Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację.

Bardziej szczegółowo

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut. Konstruktory Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut. Rozpatrzmy przykład przedstawiający klasę Prostokat: class

Bardziej szczegółowo

TEORETYCZNE PODSTAWY INFORMATYKI

TEORETYCZNE PODSTAWY INFORMATYKI 1 TEORETYCZNE PODSTAWY INFORMATYKI 16/01/2017 WFAiS UJ, Informatyka Stosowana I rok studiów, I stopień Repetytorium złożoność obliczeniowa 2 Złożoność obliczeniowa Notacja wielkie 0 Notacja Ω i Θ Rozwiązywanie

Bardziej szczegółowo

JAVA W SUPER EXPRESOWEJ PIGUŁCE

JAVA W SUPER EXPRESOWEJ PIGUŁCE JAVA W SUPER EXPRESOWEJ PIGUŁCE Obiekt Obiekty programowe to zbiór własności i zachowań (zmiennych i metod). Podobnie jak w świecie rzeczywistym obiekty posiadają swój stan i zachowanie. Komunikat Wszystkie

Bardziej szczegółowo

Sortowanie danych. Jolanta Bachan. Podstawy programowania

Sortowanie danych. Jolanta Bachan. Podstawy programowania Sortowanie danych Podstawy programowania 2013-06-06 Sortowanie przez wybieranie 9 9 9 9 9 9 10 7 7 7 7 7 10 9 1 3 3 4 10 7 7 10 10 10 10 4 4 4 4 4 4 3 3 3 3 2 2 2 2 2 2 2 3 1 1 1 1 1 1 Gurbiel et al. 2000

Bardziej szczegółowo

Języki i Techniki Programowania II. Wykład 7. Współbieżność 1

Języki i Techniki Programowania II. Wykład 7. Współbieżność 1 Języki i Techniki Programowania II Wykład 7 Współbieżność 1 Programy, Procesy, Wątki Program to zestaw instrukcji do wykonania, dane do przetworzenia, mechanizmy sterujące (stos) Proces w komputerze to

Bardziej szczegółowo

5. Model komunikujących się procesów, komunikaty

5. Model komunikujących się procesów, komunikaty Jędrzej Ułasiewicz str. 1 5. Model komunikujących się procesów, komunikaty Obecnie stosuje się następujące modele przetwarzania: Model procesów i komunikatów Model procesów komunikujących się poprzez pamięć

Bardziej szczegółowo

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej. Polimorfizm jest filarem programowania obiektowego, nie tylko jeżeli chodzi o język C++. Daje on programiście dużą elastyczność podczas pisania programu. Polimorfizm jest ściśle związany z metodami wirtualnymi.

Bardziej szczegółowo

Java - wprowadzenie. Programowanie Obiektowe Mateusz Cicheński

Java - wprowadzenie. Programowanie Obiektowe Mateusz Cicheński Java - wprowadzenie Programowanie Obiektowe Mateusz Cicheński O języku Czym jest Java Cechy charakterystyczne języka Przykładowe zastosowania Składnia języka Podstawowe typy Wybrane słowa kluczowe Plan

Bardziej szczegółowo

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018 Informatyka I Klasy i obiekty. Podstawy programowania obiektowego dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2018 Plan wykładu Pojęcie klasy Deklaracja klasy Pola i metody klasy

Bardziej szczegółowo

Java. Programowanie Obiektowe Mateusz Cicheński

Java. Programowanie Obiektowe Mateusz Cicheński Java Programowanie Obiektowe Mateusz Cicheński Wielowątkowość Proces a wątek? Thread vs Runnable sleep(), interrupt(), join() Problemy wielowątkowości Obiekty niemodyfikowalne (immutable) Serializacja

Bardziej szczegółowo

Klasy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 13

Klasy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java   1 / 13 Klasy Klasa to grupa obiektów, które mają wspólne właściwości, a obiekt jest instancją klasy. Klasa w języku Java może zawierać: pola - reprezentują stan obiektu (odniesienie do pola z kropką), methods

Bardziej szczegółowo

WSPÓŁBIEŻNOŚĆ. MATERIAŁY:

WSPÓŁBIEŻNOŚĆ. MATERIAŁY: WSPÓŁBIEŻNOŚĆ ZAGADNIENIA: procesy, wątki, synchronizacja, synchronizacja w Java 5.0 blokady, egzekutory, zbiory wątków MATERIAŁY: http://docs.oracle.com/javase/tutorial/essential/concurrency/ HTTP://USERS.UJ.EDU.PL/~CIESLA/

Bardziej szczegółowo

Analiza i projektowanie oprogramowania. Analiza i projektowanie oprogramowania 1/32

Analiza i projektowanie oprogramowania. Analiza i projektowanie oprogramowania 1/32 Analiza i projektowanie oprogramowania Analiza i projektowanie oprogramowania 1/32 Analiza i projektowanie oprogramowania 2/32 Cel analizy Celem fazy określania wymagań jest udzielenie odpowiedzi na pytanie:

Bardziej szczegółowo

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main. Część XVI C++ Funkcje Jeśli nasz program rozrósł się już do kilkudziesięciu linijek, warto pomyśleć o jego podziale na mniejsze części. Poznajmy więc funkcje. Szybko się przekonamy, że funkcja to bardzo

Bardziej szczegółowo

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static), Tworzenie obiektów Dostęp do obiektów jest realizowany przez referencje. Obiekty w języku Java są tworzone poprzez użycie słowa kluczowego new. String lan = new String( Lancuch ); Obszary pamięci w których

Bardziej szczegółowo

Wykład 5: Klasy cz. 3

Wykład 5: Klasy cz. 3 Programowanie obiektowe Wykład 5: cz. 3 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD - podstawy Konstruktor i destruktor (część I) 2 Konstruktor i destruktor KONSTRUKTOR Dla przykładu

Bardziej szczegółowo

Lab 9 Podstawy Programowania

Lab 9 Podstawy Programowania Lab 9 Podstawy Programowania (Kaja.Gutowska@cs.put.poznan.pl) Wszystkie kody/fragmenty kodów dostępne w osobnym pliku.txt. Materiały pomocnicze: Wskaźnik to specjalny rodzaj zmiennej, w której zapisany

Bardziej szczegółowo

Diagram klas UML jest statycznym diagramem, przedstawiającym strukturę aplikacji bądź systemu w paradygmacie programowania obiektowego.

Diagram klas UML jest statycznym diagramem, przedstawiającym strukturę aplikacji bądź systemu w paradygmacie programowania obiektowego. Umiejętność czytania oraz tworzenia diagramów klas UML jest podstawą w przypadku zawodu programisty. Z takimi diagramami będziesz spotykał się w przeciągu całej swojej kariery. Diagramy klas UML są zawsze

Bardziej szczegółowo

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec PROE wykład 3 klasa string, przeciążanie funkcji, operatory dr inż. Jacek Naruniec Przypomnienie z ostatnich wykładów Konstruktory/destruktory i kolejność ich wywołania w złożonej klasie. Referencja Obiekty

Bardziej szczegółowo

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut. Dziedziczenie Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut. Rozpatrzmy przykład przedstawiający klasy Student oraz Pracownik: class Student class Pracownik

Bardziej szczegółowo

Wykład 3 Składnia języka C# (cz. 2)

Wykład 3 Składnia języka C# (cz. 2) Wizualne systemy programowania Wykład 3 Składnia języka C# (cz. 2) 1 dr Artur Bartoszewski -Wizualne systemy programowania, sem. III- WYKŁAD Wizualne systemy programowania Metody 2 Metody W C# nie jest

Bardziej szczegółowo

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania 1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja nie ma parametru i zwraca wartość na zewnątrz. nie ma parametru i nie zwraca wartości na zewnątrz. ma parametr o nazwie void i zwraca

Bardziej szczegółowo

Dziedziczenie. Tomasz Borzyszkowski

Dziedziczenie. Tomasz Borzyszkowski Dziedziczenie Tomasz Borzyszkowski Podstawy Zobacz: Dziedzictwo1.java Dziedzictwo2.java Dziedziczenie jest jedną z podstawowych cech OOP ponieważ umożliwia łatwe implementowanie klasyfikacji hierarchicznych.

Bardziej szczegółowo

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki Dariusz Brzeziński Politechnika Poznańska, Instytut Informatyki Object-oriented programming Najpopularniejszy obecnie styl (paradygmat) programowania Rozwinięcie koncepcji programowania strukturalnego

Bardziej szczegółowo

PHP 5 język obiektowy

PHP 5 język obiektowy PHP 5 język obiektowy Wprowadzenie Klasa w PHP jest traktowana jak zbiór, rodzaj różnych typów danych. Stanowi przepis jak stworzyć konkretne obiekty (instancje klasy), jest definicją obiektów. Klasa reprezentuje

Bardziej szczegółowo

Programowanie obiektowe - 1.

Programowanie obiektowe - 1. Programowanie obiektowe - 1 Mariusz.Masewicz@cs.put.poznan.pl Programowanie obiektowe Programowanie obiektowe (ang. object-oriented programming) to metodologia tworzenia programów komputerowych, która

Bardziej szczegółowo

dr inż. Konrad Sobolewski Politechnika Warszawska Informatyka 1

dr inż. Konrad Sobolewski Politechnika Warszawska Informatyka 1 dr inż. Konrad Sobolewski Politechnika Warszawska Informatyka 1 Cel wykładu Definicja, miejsce, rola i zadania systemu operacyjnego Klasyfikacja systemów operacyjnych Zasada działanie systemu operacyjnego

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Wykład 2: Wstęp do języka Java 3/4/2013 S.Deniziak: Programowanie obiektowe - Java 1 Cechy języka Java Wszystko jest obiektem Nie ma zmiennych globalnych Nie ma funkcji globalnych

Bardziej szczegółowo

Wykład 3. Procesy i wątki. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Wykład 3. Procesy i wątki. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB Wykład 3 Procesy i wątki Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB Pojęcie procesu Program = plik wykonywalny na dysku Proces = uruchomiony i wykonywany program w pamięci

Bardziej szczegółowo

Podstawy Programowania Obiektowego

Podstawy Programowania Obiektowego Podstawy Programowania Obiektowego Wprowadzenie do programowania obiektowego. Pojęcie struktury i klasy. Spotkanie 03 Dr inż. Dariusz JĘDRZEJCZYK Tematyka wykładu Idea programowania obiektowego Definicja

Bardziej szczegółowo

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p. Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni Wykład 3 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji Abstrakcja funkcyjna Struktury Klasy hermetyzacja

Bardziej szczegółowo

Język JAVA podstawy. wykład 1, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Język JAVA podstawy. wykład 1, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna Język JAVA podstawy wykład 1, część 3 1 Język JAVA podstawy Plan wykładu: 1. Krótka historia Javy 2. Jak przygotować sobie środowisko programistyczne 3. Opis środowiska JDK 4. Tworzenie programu krok po

Bardziej szczegółowo

Procesy i wątki. Blok kontrolny procesu. Proces. Proces - elementy. Stan procesu

Procesy i wątki. Blok kontrolny procesu. Proces. Proces - elementy. Stan procesu Proces Procesy i wątki Proces jest wykonywanym programem. Wykonanie procesu musi przebiegać w sposób sekwencyjny ( w dowolnej chwili na zamówienie naszego procesu może być wykonany co najwyżej jeden rozkaz

Bardziej szczegółowo

TEMAT : KLASY DZIEDZICZENIE

TEMAT : KLASY DZIEDZICZENIE TEMAT : KLASY DZIEDZICZENIE Wprowadzenie do dziedziczenia w języku C++ Język C++ możliwa tworzenie nowej klasy (nazywanej klasą pochodną) w oparciu o pewną wcześniej zdefiniowaną klasę (nazywaną klasą

Bardziej szczegółowo