Programowanie współbieżne i rozproszone/PWR Ćwiczenia Linda: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Mengel (dyskusja | edycje)
Mengel (dyskusja | edycje)
 
(Nie pokazano 10 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 7: Linia 7:
=== Rozwiązanie pierwsze ===
=== Rozwiązanie pierwsze ===


Załóżmy, że początkowo w przestrzenie krotek znajduje się <math>M</math> egzemplarzy krotki postaci <tt>('A')</tt> i <math>N</math> egzemplarzy krotki <tt>('B')</tt>. Procesy grupy pierwszej muszą dostać zasób <tt>A</tt>, zabierają więc z przestrzeni jeden egzemplarz krotki <tt>('A')</tt>. Po skorzystaniu z zasobu, krotka jest oddawana do przestrzeni. Proces pierwszej grupy można więc zapisać tak:
Załóżmy, że początkowo w przestrzenie krotek znajduje się <math>M</math> egzemplarzy krotki postaci <tt>('A')</tt> i <math>N</math> egzemplarzy krotki <tt>('B')</tt>. Procesy grupy pierwszej muszą dostać zasób <tt>A</tt>, zabierają więc z przestrzeni jeden egzemplarz krotki <tt>('A')</tt>. Po skorzystaniu z zasobu, krotka jest oddawana do przestrzeni. Spróbuj zapisać proces pierwszej grupy.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">  
<div class="mw-collapsible mw-made=collapsible mw-collapsed">  
Pokaż treść procesu  
Treść procesu grupy pierwszej
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''process''' grupa1;
<source>
process grupa1;
begin
  while true do
  begin
    wlasne_sprawy;
    input('A')
    korzystaj('A');
    output('A')
  end
end;
</source>
</div>
</div>
 
Procesy drugiej grupy chcą otrzymać dowolny zasób preferując jednak <tt>A</tt>. Spróbuj zapisać proces drugiej grupy.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Proces grupy drugiej
<div class="mw-collapsible-content" style="display:none">
Narzuca się następujące rozwiązanie. Proces próbuje pobrać <tt>A</tt>. Jeśli mu się to nie uda (funkcja <tt>try_input</tt> da w wyniku fałsz), to zasobu <tt>A</tt> nie ma i trzeba wziąć <tt>B</tt>
  '''process''' grupa2;
'''var'''
  jaki: char;
  '''begin'''
  '''begin'''
   '''while''' true '''do'''  
   '''while''' true '''do'''  
   '''begin'''
   '''begin'''
     wlasne_sprawy;
     wlasne_sprawy;
     input('A')
     '''if''' try_input('A') '''then'''
     korzystaj('A');
      jaki := 'A'
     output('A')
    '''else'''
     '''begin'''
      input('B');
      jaki := 'B'
    '''end''';
    korzystaj(jaki);
     output(jaki)
   '''end'''
   '''end'''
  '''end''';
  '''end''';
</div>
Nie jest to jednak dobre rozwiązanie. Po tym, jak proces sprawdzi, że nie ma zasobów <tt>A</tt>, inny proces może taki zasób oddać. Jeśli ponadto nie ma już dostępnych zasobów <tt>B</tt>, to proces będzie czekał na <tt>B</tt> mając dostępny zasób <tt>A</tt>!
</div>
 
Treść procesu drugiej grupy wygląda następująco:


W prawidłowym rozwiązaniu proces po upewnieniu się, że nie ma dla niego zasobu <tt>A</tt> powinien oczekiwać na dostępność '''dowolnego''' zasobu:
  '''process''' grupa2;
  '''process''' grupa2;
  '''var'''
  '''var'''
Linia 41: Linia 67:
   '''end'''
   '''end'''
  '''end''';
  '''end''';
 
</div>
proces grupy trzeciej bardzo przypomina proces z grupy drugiej:
</div>
 
Procesy grupy trzeciej działają bardzo podobnie do procesów grupy drugiej z tym, że pobieranie z przestrzeni krotek jest nieblokujące.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">Treść procesu grupy trzeciej
<div class="mw-collapsible-content" style="display:none">
  '''process''' grupa3;
  '''process''' grupa3;
  '''var'''  
  '''var'''  
Linia 64: Linia 92:
   '''end'''
   '''end'''
  '''end''';
  '''end''';
</div>
</div>


=== Rozwiązanie drugie ===
=== Rozwiązanie drugie ===
Rozwiązanie drugie polega na umieszczeniu w przestrzeni krotek jedynie dwóch krotek:
Rozwiązanie drugie polega na umieszczeniu w przestrzeni krotek postaci:
* <tt>('A', wolnychA)</tt>, gdzie <tt>wolnychA</tt< jest liczbą dostępnych zasobów typu <tt>A</tt>
* <tt>('A', wolnychA)</tt>, gdzie <tt>wolnychA</tt> jest liczbą aktualnie dostępnych zasobów typu <tt>A</tt>
* <tt>('B', wolnychB)</tt>, gdzie <tt>wolnychA</tt< jest liczbą dostępnych zasobów typu <tt>A</tt>
* <tt>('B', wolnychB)</tt>, gdzie <tt>wolnychB</tt> jest liczbą aktualnie dostępnych zasobów typu <tt>B</tt>
 
<!-- Jak początkowo wygląda zawartość przestrzeni krotek?
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Odpowiedź
<div class="mw-collapsible-content" style="display:none">
<tt>('A', N)</tt>
<tt>('B', M)</tt>
</div>
</div>
Spróbujmy zapisać treści procesów przy takich założeniach. Proces grupy pierwszej wyjmuje krotkę zliczającą wolne zasoby <tt>A</tt> z przestrzeni i zmniejsza ich liczbę.
input ('A', ile: integer);
'''if''' ile > 0 '''then'''
  output ('A', ile-1)
'''else'''
    ??????
Co jednak zrobić, jeśli licznik wolnych zasobów już jest zerem? Proces powinien poczekać, a jedynym sposobem zawieszenia procesu jest wykonanie przez niego operacji <tt>input</tt> na krotce, której nie ma w przestrzeni. Czyli potrzebna jest jeszcze jedna krotka, powiedzmy postaci
<tt>('SĄ A')</tt>. Krotka przebywa w przestrzeni jedynie wówczas, gdy są jeszcze dostępne zasoby typu <tt>A</tt>. Spróbujmy zapisać odpowiedni fragment kodu:
read ('SĄ_A');              /* Czekamy aż będą zasoby A */
input ('A', ile: integer);
ile := ile - 1;
output ('A', ile);          /* Zmniejszamy liczbę wolnych zasobów A */
'''if''' ile = 0 '''then'''      /* Zabieramy krotkę, jeśli nie ma wolnych A */
  input ('SĄ A') 
 
--> 
 
 
 
 
 


Spróbuj zapisać treści procesów przy takich założeniach. W razie potrzeby możesz rozbudować powyższe krotki o dodatkowe elementy.
W razie potrzeby możesz rozbudować powyższe krotki o dodatkowe elementy.


== Synchronizacja grupowa ==
== Synchronizacja grupowa ==

Aktualna wersja na dzień 17:25, 18 paź 2006

Zasoby dwóch typów

Zadanie to pochodzi z książki Z.Weiss, T.Gruźlewski Programowanie współbieżne i rozproszone.

W systemie znajdują się dwa typy nierozróżnialnych zasobów A i B. Jest M>0 egzemplarzy zasobu A oraz N>0 egzemplarzy zasobu B. W takim systemie działają trzy grupy procesów. Procesy z grupy pierwszej cyklicznie wykonują własne sprawy, po czym żądają jednego egzemplarza zasobu A, w razie potrzeby czekając aż będzie on dostępny. Procesy z drugiej grupy żądają jednego egzemplarza zasobu A ale jeśli nie jest on dostępny czekają na zasób dowolny. Procesy z trzeciej grupy żądają jednego egzemplarza dowolnego zasobu, ale nie czekają, jeśli żaden nie jest dostępny. Zapisz treść poszczególnych procesów w Lindzie.

Rozwiązanie pierwsze

Załóżmy, że początkowo w przestrzenie krotek znajduje się M egzemplarzy krotki postaci ('A') i N egzemplarzy krotki ('B'). Procesy grupy pierwszej muszą dostać zasób A, zabierają więc z przestrzeni jeden egzemplarz krotki ('A'). Po skorzystaniu z zasobu, krotka jest oddawana do przestrzeni. Spróbuj zapisać proces pierwszej grupy.

Treść procesu grupy pierwszej

Procesy drugiej grupy chcą otrzymać dowolny zasób preferując jednak A. Spróbuj zapisać proces drugiej grupy.

Proces grupy drugiej

Procesy grupy trzeciej działają bardzo podobnie do procesów grupy drugiej z tym, że pobieranie z przestrzeni krotek jest nieblokujące.

Treść procesu grupy trzeciej

Rozwiązanie drugie

Rozwiązanie drugie polega na umieszczeniu w przestrzeni krotek postaci:

  • ('A', wolnychA), gdzie wolnychA jest liczbą aktualnie dostępnych zasobów typu A
  • ('B', wolnychB), gdzie wolnychB jest liczbą aktualnie dostępnych zasobów typu B




W razie potrzeby możesz rozbudować powyższe krotki o dodatkowe elementy.

Synchronizacja grupowa

Treść tego zadania przedstawimy w formie anegdoty. Z zespołu boisk korzysta N>0 drużyn. Każda drużyna składa się z K>1 zawodników, przy czym zawodnik jest na stałe przypisany do konkretnej drużyny. Każdy zawodnik cyklicznie (tj. w pętli nieskończonej):

  • załatwia własne sprawy,
  • udaje się na boisko,
  • oczekuje aż zbierze się jego drużyna,
  • oczekuje aż zbierze się jakaś inna drużyna,
  • rozgrywa mecz.

Po przyjściu na boisko zawodnik oczekuje na przyjście wszystkich zawodników z jego drużyny oraz na skompletowanie się innej drużyny. Gdy tylko są dwie kompletne drużyny rozpoczyna się mecz. Każdy zawodnich z tych drużyn wywołuje wówczas predefiniowaną procedurę mecz (z_kim: 1..N), gdzie z_kim jest numerem drużyny przeciwnej. Zawodnik może w każdej chwili zejść z boiska (zakończyć wykonanie procedury mecz). Pozostali zawodnicy kontynuują wówczas grę, nawet jeśli na boisku pozostanie tylko jeden zawodnik. Zawodnik, który zakończył grę nie może jednak wrócić na boisko, tzn. aby ponownie rozpocząć mecz musi najpierw poczekać aż ponownie zbiorą się wszyscy gracze jego drużyny oraz pewna drużyna przeciwna. Zakładamy, że boisk jest co najmniej N/2. Zapisz w Lindzie treść procesu Zawodnik (dr: 1..N)

Sortowanie

Zapisz w Lindzie algorytm sortowania N>0 liczb naturalnych. Załóż, że początkowo proces Inicjator umieszcza w przestrzeni N ponumerowanych liczb naturalnych, korzystając z predefiniowanej funkcji losuj przekazującej w wyniku liczby naturalne z przedziału [1,n]. Sortowanie wykonywane jest przez K>0 procesów, z których każdy w kolejnym cyklu dokonuje jednego porównania i w razie potrzeby zamienia ich kolejność.