Programowanie współbieżne Wykład 4. Rafał Skinderowicz

Podobne dokumenty
Przetwarzanie wielowątkowe przetwarzanie współbieżne. Krzysztof Banaś Obliczenia równoległe 1

Przeplot. Synchronizacja procesów. Cel i metody synchronizacji procesów. Wątki współbieżne

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

Ingerencja w kod systemu operacyjnego (przerwania) Programowanie na niskim poziomie (instrukcje specjalne) Trudności implementacyjne (alg.

Semafory. // G - globalna dla wszystkich. // Wada - aktywne oczekiwanie Test_and_Set(Li); exit when Li = 0; end loop sekcja_krytyczna(i); G := 0;

Wykład 4. Synchronizacja procesów (i wątków) cześć I. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

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

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

Wprowadzenie do programowania współbieżnego

Systemy operacyjne. Zajęcia 11. Monitory

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

synchronizacji procesów

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

procesów Współbieżność i synchronizacja procesów Wykład prowadzą: Jerzy Brzeziński Dariusz Wawrzyniak

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

synchronizacji procesów

Programowanie Równoległe i Rozproszone

Synchronizacja procesów i wątków

SOP2 - semafory. grudzień

Monitory. Jarosław Kuchta

Proces z sekcją krytyczną. Synchronizacja procesów. Synchronizacja procesów, cd. Synchronizacja procesów, cd. Synchronizacja procesów, cd

Programowanie współbieżne Wykład 5. Rafał Skinderowicz

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

Semafory. - aktywne oczekiwanie =GRGDWNRZ\PZVSDUFLHPVSU]WRZ\P 6SHFMDOQDLQVWUXNFMDPDV]\QRZDUHDOL]XMFDDWRPRZ\]DSLVL odczyt, np.

Klasyczne problemy współbieżności. Problem producenta i konsumenta Problem czytelników i pisarzy Problem pięciu filozofów

Wykład 5. Synchronizacja (część II) Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Podstawy współbieżności

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

Problemy czytelników i pisarzy oraz 5 ucztujących filozofów

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

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

Systemy operacyjne III

Wykład 4. Synchronizacja procesów (i wątków) cześć I. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Problemy współbieżności

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

WYKŁAD 4 SEMAPHORES (CIĄG DALSZY) Przykład 6 Problem czytelników i pisarzy. Wykład 4 strona 1/24

Proces z sekcją krytyczną. Synchronizacja procesów. Synchronizacja procesów, cd. Synchronizacja procesów, cd. Synchronizacja procesów, cd

Programowanie wspóªbie»ne

Mechanizmy komunikacji. spotkania symetryczne (język CSP) spotkania asymetryczne (Ada) przestrzenie krotek (Linda) potoki, komunikaty i kanały (Unix)

Systemy Operacyjne synchronizacja i komunikacja procesów

Modelowanie procesów współbieżnych

Synchronizacja procesów

J. Ułasiewicz Programowanie aplikacji współbieżnych 1

Kurs programowania. Wykład 8. Wojciech Macyna

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

Programowanie wspóªbie»ne

Java. Programowanie Obiektowe Mateusz Cicheński

4. Procesy pojęcia podstawowe

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

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

Programowanie współbieżne i rozproszone w języku Java

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

Programowanie wielowątkowe. Tomasz Borzyszkowski

Strategia "dziel i zwyciężaj"

Model pamięci. Rafał Skinderowicz

Gdy kilka procesów czyta a przynajmniej jeden dokonuje zapisu wynik odczytu zależeć może od sposobu realizacji przeplotu.

3URJUDPRZDQLHZVSyáELH*QHZVWS

J. Ułasiewicz Programowanie aplikacji współbieżnych 1

Programowanie współbieżne Wykład 2. Rafał Skinderowicz

Klasyczne problemy synchronizacji

4. Procesy pojęcia podstawowe

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

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

Multiprocessor Shared-Memory Information Exchange. Damian Klata, Adam Bułak

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

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

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

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

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

Język Java wątki (streszczenie)

Programowanie komputerów

Semafor ustaw_semafor(key_t nazwa, int start); Semafor usun_semafor(semafor sem); void signal(semafor sem); void wait(semafor sem);

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

Algorytmy i Struktury Danych

Programowanie współbieżne Wykład 7. Iwona Kochaoska

Mechanizmy pracy równoległej. Jarosław Kuchta

Dokumentacja do API Javy.

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

Programowanie współbieżne Zadanie numer 3 Monitory

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Zaawansowany kurs języka Python

SYSTEMY OPERACYJNE WYKLAD 6 - procesy

Sortowanie przez wstawianie Insertion Sort

Systemowe mechanizmy synchronizacji procesów

Generatory. Michał R. Przybyłek

Program jest więc strukturą statyczną zapisaną na jakimś nośniku. Natomiast proces jest wykonującym się programem.

Proces y i y w i ąt ą ki

Algorytmy z powrotami. Algorytm minimax

INFORMATYKA W SZKOLE. Podyplomowe Studia Pedagogiczne. Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227

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

Programowanie współbieżne Zadanie 5 - Podstawowe problemy programowania współbieżnego

Model pamięci. Rafał Skinderowicz

Wykład 4: Klasy i Metody

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Podstawy programowania obiektowego

Analiza algorytmów zadania podstawowe

Języki i metody programowania Java INF302W Wykład 2 (część 1)

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

4. Procesy pojęcia podstawowe

2. Tablice. Tablice jednowymiarowe - wektory. Algorytmy i Struktury Danych

Transkrypt:

Programowanie współbieżne Wykład 4 Rafał Skinderowicz

Semafory Algorytmy synchronizacyjne omawiane poprzednio opierały się na atomowych instrukcjach odczytu i zapisu do pamięci, ewentualnie dodatkowych rozkazach typu Read-Modify-Write Algorytmy te stosowały aktywne oczekiwanie (ang. spin-locks) w większości przypadków nieefektywne Semafory (ang. semaphores) konstrukcje programistyczne wyższego poziomu, ułatwiające synchronizację w programach współbieżnych 2

Stany procesu powtórka Zazwyczaj jest więcej procesów (lub wątków) niż fizycznych procesorów (rdzeni) Procesy muszą współdzielić procesor Proces, który chce się wykonywać jest procesem gotowym Proces, który otrzymał czas procesora jest procesem aktywnym W każdym momencie tylko jeden proces jest w stanie aktywnym Gdy żaden proces nie jest gotowy do wykonania, to wykonywany jest proces jałowy (bezczynności, ang. idle) Przydziałem czasu procesora poszczególnym procesom zajmuje się planista (ang. scheduler) 3

Procesy wstrzymane Konstrukcja semafora zakłada istnienie dodatkowego stanu procesu wstrzymanego Proces wstrzymany nie jest gotowy do wykonania Proces wstrzymany może jedynie być obudzony lub wznowiony na skutek zdarzenia zewnętrznego zmieniającego jego stan ze wstrzymanego na gotowy Proces wstrzymany nie zużywa czasu procesora czekanie nieaktywne Procesy zablokowane są zapamiętywane w dodatkowej strukturze danych (zbiór, lista, kolejka) 4

Stany procesu diagram nieaktywny gotowy aktywny (wykonywany) zakończony wstrzymany Początkowo proces jest nieaktywny W pewnym momencie staje się gotowy (zostaje aktywowany) Po przydziale czasu procesora przez planistę staje się aktywny, po wyczerpaniu przydziału wraca do stanu gotowości Na skutek wykonania niektórych operacji wątek może stać się wstrzymany Kiedy proces wykona ostatnią instrukcję staje się zakończony 5

Semafory Semafory zostały zaproponowane przez holenderskiego naukowca E. Dijkstrę w 1968 r. Na poziomie konceptualnym semafor, pełni po prostu rolę licznika dostępnych w danym momencie zasobów Mogą zostać zaimplementowane bez konieczności aktywnego oczekiwania (ang. busy-waiting) Rysunek 1: Edsger W. Dijkstra (autor: Hamilton Richards) 6

Semafory Nazwa semafor została użyta przez analogię do idei semaforów kolejowych: Zasobami współdzielonymi przez pociągi są tory 7

Semafory Nazwa semafor została użyta przez analogię do idei semaforów kolejowych: Zasobami współdzielonymi przez pociągi są tory Jeżeli dany tor jest w danym momencie niedostępny, to semafor jest opuszczony (zamknięty) 7

Semafory Nazwa semafor została użyta przez analogię do idei semaforów kolejowych: Zasobami współdzielonymi przez pociągi są tory Jeżeli dany tor jest w danym momencie niedostępny, to semafor jest opuszczony (zamknięty) Jeżeli dany tor jest wolny, to semafor jest podniesiony (otwarty) 7

Semafory Nazwa semafor została użyta przez analogię do idei semaforów kolejowych: Zasobami współdzielonymi przez pociągi są tory Jeżeli dany tor jest w danym momencie niedostępny, to semafor jest opuszczony (zamknięty) Jeżeli dany tor jest wolny, to semafor jest podniesiony (otwarty) Na każdym torze w każdej chwili może znajdować się maksymalnie jeden pociąg 7

Semafory analogia nr 2 Załóżmy, że mamy napisać program symulujący korzystanie z parkingu podziemnego parking mieści 20 samochodów wjazd na parking zamykany jest szlabanem szlaban otwiera się po naciśnięciu przycisku, jeżeli na parkingu są jeszcze wolne miejsca jeżeli wszystkie stanowiska są zajęte szlaban wjazdowy pozostaje opuszczony 8

Semafory analogia nr 2 Załóżmy, że mamy napisać program symulujący korzystanie z parkingu podziemnego parking mieści 20 samochodów wjazd na parking zamykany jest szlabanem szlaban otwiera się po naciśnięciu przycisku, jeżeli na parkingu są jeszcze wolne miejsca jeżeli wszystkie stanowiska są zajęte szlaban wjazdowy pozostaje opuszczony Zauważmy, że system sterujący nie musi zapisywać, który samochów zajmuje które stanowisko wystarczy aktualna liczba samochodów na parkingu 8

Semafory analogia nr 2 W podanym przykładzie: współdzielonymi zasobami są miejsca parkingowe system sterujący szlabanem pełni rolę semafora: początkowo wartość semafora to 20 kiedy samochód wjeżdża na parking, semafor zmniejszany jest o 1 kiedy samochód wyjeżdża z parkingu semafor zwiększany jest o 1 jeżeli semafor ma wartość 0, to znaczy, że wszystkie miejsca są zajęte i kolejni kierowcy muszą poczekać na zwolnienie miejsca 9

Semafory definicja Semafor S to abstrakcyjny typ danych z dwoma polami: S.V liczba całkowita nieujemna S.L zbiór wstrzymanych procesów 10

Semafory definicja Semafor S to abstrakcyjny typ danych z dwoma polami: S.V liczba całkowita nieujemna S.L zbiór wstrzymanych procesów Na semaforze można wykonywać tylko dwie operacje atomowe: operację wait(s) (w lit. czasem P (S)) oczekiwanie na podniesienie semafora operację signal(s) (w lit. czasem V (S)) podnosi semafor 10

Semafory definicja Semafor S to abstrakcyjny typ danych z dwoma polami: S.V liczba całkowita nieujemna S.L zbiór wstrzymanych procesów Na semaforze można wykonywać tylko dwie operacje atomowe: operację wait(s) (w lit. czasem P (S)) oczekiwanie na podniesienie semafora operację signal(s) (w lit. czasem V (S)) podnosi semafor Semafor musi zostać zainicjowany wartością początkową Zbiór S.L początkowo jest pusty Programista nie musi mieć bezpośredniego dostępu do wartości pól S.V oraz S.L 10

Semafor operacja wait wait(s): if S.V > 0 S.V S.V 1 else S.L S.L {A} A.stan wstrzymany Jeżeli wartość semafora (składowa V ) jest niezerowa, to następuje jej zmniejszenie o 1 i proces A wykonuje się dalej 11

Semafor operacja wait wait(s): if S.V > 0 S.V S.V 1 else S.L S.L {A} A.stan wstrzymany Jeżeli wartość semafora (składowa V ) jest niezerowa, to następuje jej zmniejszenie o 1 i proces A wykonuje się dalej Jeżeli wartość ta jest równa zero, to proces A zostaje wstrzymany proces A jest wstrzymany na semaforze S 11

Semafor operacja signal signal(s): if S.L = S.V S.V + 1 else niech A będzie dowolnym elementem zbioru S.L S.L S.L {A} A.stan gotowy Jeżeli zbiór procesów wstrzymanych na semaforze S jest pusty, to wartość (składowej S.L) semafora zwiększa się o 1 12

Semafor operacja signal signal(s): if S.L = S.V S.V + 1 else niech A będzie dowolnym elementem zbioru S.L S.L S.L {A} A.stan gotowy Jeżeli zbiór procesów wstrzymanych na semaforze S jest pusty, to wartość (składowej S.L) semafora zwiększa się o 1 W przeciwnym razie ze zbioru procesów wstrzymanych budzony (usuwany) jest dowolny ze wstrzymanych wcześniej procesów 12

Rodzaje semaforów Semafor, którego składowa S.L przyjmuje jedynie wartości 0 lub 1 nazywany jest semaforem binarnym Semafor, którego składowa S.L może przyjmować dowolne wartości nieujemne, to semafor ogólny Semafor może być zamknięty przez jeden proces, a podniesiony przez inny 13

Rodzaje semaforów Semafor, którego składowa S.L przyjmuje jedynie wartości 0 lub 1 nazywany jest semaforem binarnym Semafor, którego składowa S.L może przyjmować dowolne wartości nieujemne, to semafor ogólny Semafor może być zamknięty przez jeden proces, a podniesiony przez inny Blokady są zakładane i zwalniane przez ten sam proces Próba zwolnienia blokady założonej przez inny proces skutkuje błędem 13

Semafor binarny działanie Operacja wait(s) jak dla semafora ogólnego Operacja signal(s): if S.V = 1 // nieokreślone! else if S.L = S.V 1 else niech A będzie dowolnym elementem zbioru S.L S.L S.L {A} A.stan gotowy 14

Semafory budzenie procesów Definicja operacji signal(s) nie podaje, który z procesów wstrzymanych na semaforze stanie się gotowy Decyzja zależy od implementacji semafora, a ściślej kolejności w której procesy są wzbudzane Nie ma to wpływu na własności bezpieczeństwa semaforów, jednak może mieć wpływ na własność żywotności możliwe zagłodzenie 15

Zastosowania semaforów Semafory umożliwiają łatwe rozwiązanie problemów: synchronizacji dostępu do zasobów: niekoniecznie wyłączny dostęp również ograniczony dostęp do krytycznych zasobów, tzn. dla więcej, niż jednego procesu jednocześnie synchronizacji kolejności wykonywania proces musi oczekiwać na zakończenie operacji wykonywanych przez inne procesy, by kontynuować działanie 16

Semafory binarne a blokady Obie konstrukcje mają dwa stany: otwarty, zamknięty Różnią się jednak celem: blokady stosowane są do ochrony zasobów przed jednoczesną modyfikacją semafory stosowane są do synchronizacji między wątkami semafor może być początkowo zamknięty 17

Semafory binarne a blokady Obie konstrukcje mają dwa stany: otwarty, zamknięty Różnią się jednak celem: blokady stosowane są do ochrony zasobów przed jednoczesną modyfikacją semafory stosowane są do synchronizacji między wątkami semafor może być początkowo zamknięty 1 binary semaphore data_ready = 0 // współdzielony semafor 2 T data = null 1 // Proces 1: 2 3 data = gather_sensor_data() 4 signal(data_ready) 1 // Proces 2: 2 3 wait(data_ready) 4 process(data) 17

Semafory a blokady Semafory i blokady często stosowane są razem 1 semaphore data_ready = 0 // semafor ogólny 2 Queue queue // współdzielona kolejka 3 lock queue_lock // blokada do WW dla kolejki 1 // Proces 1: 2 3 while (true) { 4 data = gather_sensor_data() 5 queue_lock.lock() 6 queue.push(data) 7 queue_lock.unlock() 8 signal(data_ready) 9 } 1 // Proces 2: 2 3 while (true) { 4 wait(data_ready) 5 queue_lock.lock() 6 data = queue.pop() 7 queue_lock.unlock() 8 process(data) 9 } 18

Wzajemne wykluczanie semafory Za pomocą semafora binarnego można również rozwiązać problem wzajemnego wykluczania binarny semafor S 1 // współdzielony semafor // Proces P i while (true) { sekcja lokalna P i wait(s) sekcja krytyczna P i signal(s) } Działanie analogiczne do blokad (ang. lock) 19

Wzajemne wykluczanie przykład // Proces P while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } // Proces Q while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } 20

Wzajemne wykluczanie przykład // Proces P while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } // Proces Q while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } 21

Wzajemne wykluczanie przykład // Proces P while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } // Proces Q while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } 22

Wzajemne wykluczanie przykład // Proces P while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } // Proces Q while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } Proces Q został wstrzymany, ponieważ wartość semafora została wcześniej zmieniona na 0 przez proces P 23

Wzajemne wykluczanie przykład // Proces P while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } // Proces Q while (true) { sekcja lokalna wait(s) sekcja krytyczna signal(s) } Wykonanie signal(s) przez proces P powoduje wzbudzenie procesu Q wstrzymanego wcześniej na semaforze Q 24

Własności semaforowego rozwiązania problemu WW Wzajemne wykluczanie: tak Brak zakleszczenia: tak Brak zagłodzenia: tak, ale tylko dla 2 procesów w przypadku większej liczby procesów (> 2) brak zagłodzenia jest gwarantowany jedynie w przypadku silnych semaforów Dodatkowo: prostota, np. w porównaniu do alg. Petersona, czy piekarnianego brak aktywnego oczekiwania 25

Semafory a uczciwość Semafor silny (uczciwy) to taki który gwarantuje, że jeżeli proces został wstrzymany na semaforze, to zostanie w końcu wzbudzony (stanie się gotowy) niezależnie od tego jak wiele procesów wstrzymano na semaforze Wystarczy, by wstrzymane na semaforze procesy (zbiór S.L) były przechowywane w kolejce (FIFO) Przy N procesach, w kolejce S.L może znajdować się N 1 procesów, więc wystarczy N 1 operacji signal(s), tak by wszystkie z nich zostały wzbudzone Semafor słaby to semafor, który nie gwarantuje, że proces zostanie wzbudzony możliwe zagłodzenie Przykładowo, wzbudzany jest losowo wybrany proces 26

Przykład sortowanie przez scalanie Założenia: dana jest tablica A liczb całkowitych o rozmiarze N (N 2) elementów należy posortować jej elementy dzieląc pracę między 3 współbieżne procesy oznaczone A, B i C Procesy 1. i 2. mają za zadanie posortować połówki tablicy, odpowiednio A[1,..., m] oraz A[m + 1,..., N], gdzie m = N/2 Proces 3. scala posortowane połówki tablicy w posortowaną całość (można to zrobić w czasie O(N)) 27

Rozwiązanie // zmienne globalne A array[n] binarny semafor S1 0 binarny semafor S2 0 // Proces A: sortuj(a[1,..., m]) signal(s1) // Proces B: sortuj(a[m + 1,..., N]) signal(s2) // Proces C: wait(s1) wait(s2) scal(a[1,..., m], A[m + 1,..., N]) 28

Rozwiązanie // zmienne globalne A array[n] binarny semafor S1 0 binarny semafor S2 0 // Proces A: sortuj(a[1,..., m]) signal(s1) // Proces B: sortuj(a[m + 1,..., N]) signal(s2) // Proces C: wait(s1) wait(s2) scal(a[1,..., m], A[m + 1,..., N]) Problem ten można również rozwiązać za pomocą jednego semafora ogólnego - jak? 28

Problem producenta konsumenta Dane są dwa rodzaje procesów: Producenci producent wykonuje instrukcję produkuj tworząc dane, które przesyłane są konsumentom Konsumenci po odbiorze danych od producenta konsument wykonuje operację konsumuj przetwarzającą odebrane dane 29

Problem producenta konsumenta Dane są dwa rodzaje procesów: Producenci producent wykonuje instrukcję produkuj tworząc dane, które przesyłane są konsumentom Konsumenci po odbiorze danych od producenta konsument wykonuje operację konsumuj przetwarzającą odebrane dane Komunikacja między producentami a konsumentami może być zrealizowana na dwa sposoby: 29

Problem producenta konsumenta Dane są dwa rodzaje procesów: Producenci producent wykonuje instrukcję produkuj tworząc dane, które przesyłane są konsumentom Konsumenci po odbiorze danych od producenta konsument wykonuje operację konsumuj przetwarzającą odebrane dane Komunikacja między producentami a konsumentami może być zrealizowana na dwa sposoby: synchroniczny po wykonaniu operacji produkuj producent oczekuje na odebranie danych przez konsumentów 29

Problem producenta konsumenta Dane są dwa rodzaje procesów: Producenci producent wykonuje instrukcję produkuj tworząc dane, które przesyłane są konsumentom Konsumenci po odbiorze danych od producenta konsument wykonuje operację konsumuj przetwarzającą odebrane dane Komunikacja między producentami a konsumentami może być zrealizowana na dwa sposoby: synchroniczny po wykonaniu operacji produkuj producent oczekuje na odebranie danych przez konsumentów asynchroniczny dane wyprodukowane przez producenta gromadzone są w buforze, z którego pobierane są przez konsumentów 29

Producent-konsument przykłady Producent Klawiatura Edytor tekstu Joystick Gra komputerowa Łącza komunikacyjne Przeglądarka internetowa Aplikacja kliencka Konsument System operacyjny Drukarka Gra komputerowa Ekran Przeglądarka internetowa Łącza komunikacyjne Baza danych 30

Producent-konsument synchronizacja Konsument nie może pobierać danych z pustego bufora Producent nie może wstawiać danych do pełnego bufora bufor o nieskończonej pojemności nie istnieje próba wstawienia do pełnego bufora skutkowałaby utratą danych wstawianych, bądź zastępowanych 31

Producent-konsument nieskończony bufor Jak wspomniano, bufor o nieskończonej pojemności nie istnieje, ale jeżeli: jego rozmiar jest bardzo duży, tempo odbierania danych przez konsumenta jest porównywalne z tempem produkcji to można uniknąć narzutu wynikającego z konieczności synchronizacji próby wstawienia do pełnego bufora konieczne jest jedynie synchronizowanie prób odbierania danych przez konsumenta 32

Producent-konsument nieskończony bufor // zmienne globalne Typ bufor = array[ ] // bufor o nieograniczonej pojemności semafor ogólny niepusty = 0 // Producent Typ el int in = 0 while (true) { el = produkuj() bufor [ in ] = el in = in + 1 signal( niepusty ) } // konsument Typ el int out = 0 while (true) { wait( niepusty ) el = bufor [ out ] out = out + 1 konsumuj( l ) } 33

Producent-konsument nieskończony bufor Każde wstawienie elementu przez producenta powoduje zwiększenie wartości semafora niepusty o 1 Każde wyjęcie elementu przez konsumenta powoduje zmniejszenie wartości semafora niepusty o 1 liczba operacji wyjęcia elementów z bufora nigdy nie będzie wyższa, niż liczba wstawionych elementów W algorytmie nie dochodzi do zakleszczenia dopóki producent wykonuje signal( niepusty ), to proces konsumenta jest budzony W algorytmie nie dochodzi do zagłodzenia co najwyżej jeden proces może być wstrzymany (konsument) 34

Producent-konsument bufor jednoelementowy Załóżmy, że bufor może przechowywać tylko 1 element Warunki synchronizacji: producent musi czekać na opróżnienie bufora konsument może wyjąć element tylko z niepustego bufora Potrzebne są dwa semafory binarne: niepełny producent czeka na tym semaforze, aż konsument opróżni bufor niepusty konsument czeka na tym semaforze, aż producent wstawi element 35

Producent-konsument bufor jednoelementowy // zmienne globalne Typ bufor = array[1] semafor binarny niepusty = 0 semafor binarny niepełny = 1 // producent Typ el while (true) { el = produkuj() wait( niepełny ) bufor[ 0 ] = el signal( niepusty ) } // konsument Typ el while (true) { wait( niepusty ) el = bufor[ 0 ] signal( niepełny ) konsumuj( el ) } 36

Producent-konsument bufor ograniczony Rozmiar bufora wynosi N, N 1 Potrzebne są dwa semafory ogólne: niepełny zlicza liczbę wolnych miejsc w buforze początkowo N niepusty zlicza liczbę elementów znajdujących się w buforze początkowo 0 W każdym momencie, gdy żaden z procesów nie modyfikuje bufora zachodzi warunek: niepełny.v + niepusty.v = N 37

Producent-konsument bufor ograniczony // zmienne globalne Typ bufor = array[n] // bufor o ograniczonej pojemności semafor ogólny niepusty = 0 semafor ogólny niepełny = N // producent Typ el int in = 0 while (true) { el = produkuj() wait( niepełny ) bufor[ in ] = el in = ( in + 1 ) mod N signal( niepusty ) } // konsument Typ el int out = 0 while (true) { wait( niepusty ) el = bufor[ out ] out = ( out + 1 ) mod N signal( niepełny ) konsumuj( el ) } 38

Producent-konsument bufor ograniczony Własności przytoczonego rozwiązania: dane nie są nadpisywane zanim nie zostaną odczytane (odebrane) dane są odczytywane tylko raz dane nie są pobierane z pustego bufora dane są odczytywane w kolejności, w której zostały wyprodukowane wszystkie dane są w końcu odczytane 39

Producent-konsument warianty problemu Wielu producentów jeden konsument producenci współdzielą bufor konieczna synchronizacja dostępu dla producentów 40

Producent-konsument warianty problemu Wielu producentów jeden konsument producenci współdzielą bufor konieczna synchronizacja dostępu dla producentów Jeden producent wielu konsumentów konsumenci współdzielą bufor konieczna synchronizacja dostępu dla konsumentów 40

Producent-konsument warianty problemu Wielu producentów jeden konsument producenci współdzielą bufor konieczna synchronizacja dostępu dla producentów Jeden producent wielu konsumentów konsumenci współdzielą bufor konieczna synchronizacja dostępu dla konsumentów Wielu producentów wielu konsumentów rywalizacja między konsumentami rywalizacja między producentami 40

Problem ucztujących filozofów Pięciu filozofów siedzi przy stole i wykonuje naprzemiennie dwie czynności: myślenie i jedzenie. Na stole znajduje się misa ze spaghetti, po które sięgają filozofowie Do zjedzenia swojej porcji każdy filozof potrzebuje dwóch widelców Każdy filozof może podnieść widelec z jego lewej i prawej strony while True: myśli protokół wstępny je protokół końcowy 41

Problem ucztujących filozofów w4 f4 w3 f5 f3 w2 w0 f1 f2 w1 42

Problem ucztujących filozofów Zadanie polega na opracowaniu protokołów wstępnego i końcowego, dla których spełnione będą warunki: Filozof może jeść, gdy ma dwa widelce Dwóch filozofów nie może trzymać w tym samym czasie tego samego widelca (wzajemne wykluczanie) Brak zakleszczenia Brak zagłodzenia Niewielki narzut obliczeniowy w przypadku braku rywalizacji 43

Rozwiązanie 1 semafor binarny [] widelce = [1, 1, 1, 1, 1] // tablica semaforów // Filozof i, i {1, 2, 3, 4, 5} while True: myśli wait(widelce[i-1]) wait(widelce[i mod 5]) je signal(widelce[i-1]) signal(widelce[i mod 5]) 44

Problem ucztujących filozofów rozwiązanie 1 Rozwiązanie 1. ma własność wzajemnego wykluczania dwóch filozofów nie może podnieść jednocześnie tego samego widelca Jednak rozwązanie to może prowadzić do zakleszczenia 45

Problem ucztujących filozofów rozwiązanie 1 w4 f4 w3 f5 f3 w0 w2 f1 f2 w1 Do zakleszczenia dochodzi, gdy każdy filozof podniesie widelec po lewej stronie, ale nie zdąży podnieść prawego, bo zostanie wyprzedzony przez sąsiada 46

Rozwiązanie 2 semafor binarny [] widelce = [1, 1, 1, 1, 1] semafor ogólny jadalnia = 4 // Filozof i, i {1, 2, 3, 4, 5} while True: myśli wait(jadalnia) wait(widelce[i-1]) wait(widelce[i mod 5]) je signal(widelce[i-1]) signal(widelce[i mod 5]) signal(jadalnia) 47

Rozwiązanie 2 własności Dwóch filozofów nie może trzymać w tym samym czasie tego samego widelca (wzajemne wykluczanie): tak Brak zakleszczenia: tak Brak zagłodzenia: tak Niewielki narzut obliczeniowy w przypadku braku rywalizacji: tak 48

Rozwiązanie 3 semafor binarny [] widelce = [1, 1, 1, 1, 1] semafor ogólny jadalnia = 4 // Filozof 5 while True: myśli wait(widelce[0]) wait(widelce[4]) je signal(widelce[0]) signal(widelce[4]) 49

Rozwiązanie 3 w4 f4 w3 f5 f3 w2 w0 f1 f2 w1 Asymetria protokołów wstępnych jako przeciwdziałanie zakleszczeniu. 50

Semafory w Javie Klasa Semaphore z pakietu java.util.concurrent Pierwszy konstruktor Semaphore(int permits) parametr permits określa wartość semafora, może być ujemna Metoda acquire to odpowiednik metody wait Może rzucić wyjątek InterruptedException Metoda release to odpowiednik metody signal Drugi konstruktor przyjmuje dodatkowy parametr boolean fair Gdy fair = true, to semafor jest semaforem silnym (uczciwym), tj. obsługuje wstrzymane wątki w kolejności FIFO Gdy fair = false, to semafor jest semaforem słabym nie ma gwarancji kolejności wybudzania wstrzymanych na semaforze wątków 51

Przykład 1 import java.util.concurrent.semaphore; 2 class Zliczanie implements Runnable { 3 static volatile int licznik = 0; 4 static Semaphore sem = new Semaphore(1); // semafor binarny 5 6 public void run() { 7 for (int i = 0; i < 10; ++i) { 8 try { 9 sem.acquire(); 10 } catch(interruptedexception e) {} 11 n = n + 1; 12 s.release(); 13 } 14 } 15 public static void main(string [] args) { 16 // utworzenie i uruchomienie wątków 17... 18 } 19 } 52

Symulacja semaforów ogólnych Problem czy możemy zaimplementować semafor ogólny mając do dyspozycji jedynie semafory binarne? 53

Próba 1 // zmienne globalne int licznik = K // wart. semafora (gdy licznik < 0 to brak zasobów) semafor binarny straznik = 1 semafor binarny wolne = 0 // symulowane wait wait () { wait( straznik ) licznik = licznik - 1 if (licznik < 0) { signal( straznik ) wait( wolne ) } else { signal( straznik ) } } // symulowane signal signal () { wait( straznik ) licznik = licznik + 1 if ( licznik 0 ) { // ktoś czeka sygnalizuj signal( wolne ) } signal( straznik ) } Semafor binarny straznik używany jest do zapewnienia WW dla sekcji krytycznej modyfikującej i odczytującej licznik 54

Próba 1 c.d. Załóżmy, że wykonują się współbieżnie 4 procesy (p1, p2, p3, p4) oraz zmienna licznik = 2 // Procesy p1, p2 pójdą tą ścieżką wait () { wait( straznik ) licznik = licznik - 1 if (licznik < 0) { signal( straznik ) wait( wolne ) } else { signal( straznik ) } } // Procesy p3 i p4 zostaną wstrzymane wait () { wait( straznik ) licznik = licznik - 1 if (licznik < 0) { signal( straznik ) wait( wolne ) } else { signal( straznik ) } } // zmienne globalne licznik = -2 // wart. semafora straznik = 1 wolne = 0 55

Próba 1 wait() { wait( straznik ) licznik = licznik - 1 if (licznik < 0) { signal( straznik ) wait( wolne ) //p3 i p4 //czekają } else signal( straznik ) } signal() { wait( straznik ) licznik = licznik + 1 if ( licznik 0 ) { signal( wolne ) } signal( straznik ) } Początkowo: licznik = -2 straznik = 1 wolne = 0 p1 i p2 wykonują signal() licznik = 0 straznik = 1 wolne = 1 p3 staje się aktywny i przechodzi przez wait( wolne) licznik = 0 straznik = 1 wolne = 0 p4 jest nadal wstrzymany, mimo że nie powinien być 56

Próba 2 poprawna // poprzednia wersja wait () { wait( straznik ) licznik = licznik - 1 if (licznik < 0) { signal( straznik ) wait( wolne ) } else { signal( straznik ) } } // poprawiona wersja wait () { wait( straznik ) licznik = licznik - 1 if (licznik < 0) { signal( straznik ) wait( wolne ) } signal( straznik ) } 57

Próba 2 poprawna // poprzednia wersja signal () { wait( straznik ) licznik = licznik + 1 if ( licznik 0 ) { signal( wolne ) } signal( straznik ) } // poprawiona wersja signal () { wait( straznik ) licznik = licznik + 1 if ( licznik 0 ) { signal( wolne ) } else { signal( straznik ) } } Zmiana zapobiega możliwości wielokrotnego podniesienia semafora wolne, jeżeli nie został on wcześniej opuszczony. W Próbie 1., jeżeli p1 wykona signal(wolne), ale nie signal(straznik), to p2 nie może wykonać signal(wolne) zanim p3 nie wykona sekcji krytycznej 58

Dziedziczenie sekcji krytycznej Opisana technika nazywana jest dziedziczeniem sekcji krytycznej Proces budzony dziedziczy dostęp do sekcji krytycznej (opuszczony semafor) Po obudzeniu proces musi zwolnić (podnieść) semafor 59

Dziedziczenie sekcji krytycznej c.d. Schemat alg. z dziedziczeniem sekcji krytycznej Zawieszanie procesu: wait( straznik )... if( warunek ) { licznik = licznik + 1 signal( straznik ) wait( wolne ) // po obudzeniu sem. straznik będzie opuszczony } signal( straznik ) Budzenie procesu: wait( straznik ) if ( licznik > 0 ) { signal( wolne ) // wybudź jeden z wstrzymanych procesów } else { signal( straznik ) } 60