• Nie Znaleziono Wyników

Systemy Rozproszone - Ćwiczenie 4

N/A
N/A
Protected

Academic year: 2021

Share "Systemy Rozproszone - Ćwiczenie 4"

Copied!
6
0
0

Pełen tekst

(1)

Systemy Rozproszone - Ćwiczenie 4

1 Synchronizacja wątków: myjnia samochodowa

Poniżej znajduje się przykład ilustrujący klasyczny problem synchronizacji wąt- ków. Obiekt klasy Car jest współdzielony przez 2 wątki. Samochód może znaj- dować się w jednym w 2 stanów: nawoskowany (waxed==true) i wypolerowany (waxed==false). Na samochodzie działają 2 wątki: Waxer, którego zadaniem jest nawoskowanie samochodu, oraz Polisher, którego zadaniem jest jest wypole- rowanie samochodu. Nawoskowanie samochodu jest możliwe tylko wtedy jeżeli samochód jest wypolerowany (czyli ma stan waxed==false) i skutkuje zmianą jego stanu na waxed==true. Wypolerowanie samochodu jest możliwe tylko wte- dy jeżeli samochód jest nawoskowany (czyli ma stan waxed==true) i skutkuje jego zmianą stanu na waxed==false. Obydwa wątki wykonują swoje działania w nieskończonej pętli, a oczekiwanie wątku na osiągnięcie właściwego stanu przez samochód odbywa się w metodach waitUntilWaxed() i waitUntilPolished().

Wykonaniu działana na samochodzie (metody polish() i wax()) skutkuje zmia- ną jego stanu, i wznowieniem pracy przez oczekujący wątek. Zawieszenie pra- cy wątku uzyskuje się wywołując metodę Thread.wait(), a wznowienie pra- cy wszystkich oczekujących wątków uzyskuje się poprzez wywołanie metody Thread.notifyAll(). Wątek główny, po uruchomieniu wątków Waxer i Polisher,

odczekuje 100ms Thread.sleep(), a następnie przerywa pracę 2 wątków Thread.interrupt().

/∗ p l i k : WaxOMatic . j a v a ∗/

c l a s s Car {

boolean waxed = f a l s e ;

public synchronized void wax ( ) throws I n t e r r u p t e d E x c e p t i o n { w a i t U n t i l P o l i s h e d ( ) ;

waxed = true ; n o t i f y A l l ( ) ; }

public synchronized void p o l i s h ( ) throws I n t e r r u p t e d E x c e p t i o n { waitUntilWaxed ( ) ;

waxed = f a l s e ; n o t i f y A l l ( ) ; }

(2)

public synchronized boolean isWaxed ( ) { return waxed ;

}

private synchronized void waitUntilWaxed ( ) throws I n t e r r u p t e d E x c e p t i o n { while ( ! isWaxed ( ) ) {

System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ i s ␣ w a i t i n g ␣ u n t i l ␣ waxed " ) ;

w a i t ( ) ; }

}

private synchronized void w a i t U n t i l P o l i s h e d ( ) throws I n t e r r u p t e d E x c e p t i o n { while ( isWaxed ( ) ) {

System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ i s ␣ w a i t i n g ␣ u n t i l ␣ p o l i s h e d " ) ;

w a i t ( ) ; }

} }

c l a s s Waxer extends Thread { Car c a r ;

public Waxer ( Car c ) { c a r = c ;

}

public void run ( ) { try {

while ( true ) {

System . ou t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ i s ␣ waxing . . . " ) ;

c a r . wax ( ) ;

System . ou t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ f i n i s h e d ␣ waxing " ) ;

} }

catch ( I n t e r r u p t e d E x c e p t i o n e ) {

System . o u t . p r i n t l n ( "Waxer␣ i n t e r r u p t e d " ) ; }

} }

c l a s s P o l i s h e r extends Thread { Car c a r ;

public P o l i s h e r ( Car c ) {

(3)

c a r = c ; }

public void run ( ) { try {

while ( true ) {

System . ou t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ i s ␣ p o l i s h i n g . . . " ) ;

c a r . p o l i s h ( ) ;

System . ou t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ f i n i s h e d ␣ p o l i s h i n g " ) ;

} }

catch ( I n t e r r u p t e d E x c e p t i o n e ) {

System . o u t . p r i n t l n ( " P o l i s h e r ␣ i n t e r r u p t e d " ) ; }

} }

public c l a s s WaxOMatic {

public s t a t i c void main ( S t r i n g [ ] a r g s ) throws E x c e p t i o n { Car c a r = new Car ( ) ;

Waxer waxer = new Waxer ( c a r ) ;

P o l i s h e r p o l i s h e r = new P o l i s h e r ( c a r ) ; waxer . s t a r t ( ) ;

p o l i s h e r . s t a r t ( ) ; Thread . s l e e p ( 1 0 0 ) ; waxer . i n t e r r u p t ( ) ; p o l i s h e r . i n t e r r u p t ( ) ; }

}

Wprowadź następujące modyfikacje do programu:

• Dodaj opóznienie do metod wax() i polish polish() symulujące czas wy- konania działania na samochodzie. Jak wpłynie to na działanie programu.

• Wprowadz dodatkowy wątek do programu Washer, którego zadaniem jest mycie samochodu, w taki sposób, żeby samochód zmieniał stany w nastę- pujący sposób: waxed →polished→washed→waxed→polished→washed→

. . ..

2 Problem producenta i konsumenta

Kolejny przykład ilustruje klasycznyproblem producenta i konsumentaw odnie- sieniu do dwóch wątków działających na współdzielonym stosie WaitingStack.

(4)

Pierwszy wątek, StackPusher, pełni rolę producenta i jego zadaniem jest wkła- danie elementów na stos. Drugi wątek, StackPopper, pełni rolę konsumenta i jego zadaniem jest zdejmowania elementów ze stosu. Zwróć uwagę na metody waitForNotEmpty(), waitForFullEmpty(), push(), pop().

/∗ p l i k : W a i t i n g S t a c k . j a v a ∗/

c l a s s W a i t i n g S t a c k { i n t [ ] d a t a ;

i n t c a p a c i t y ; i n t c u r r e n t = −1;

public W a i t i n g S t a c k ( i n t c o u n t ) { c a p a c i t y = c o u n t ;

d a t a = new i n t [ c o u n t ] ; }

public synchronized void push ( i n t number ) throws I n t e r r u p t e d E x c e p t i o n {

S t r i n g name = Thread . c u r r e n t T h r e a d ( ) . getName ( ) ; System . ou t . f o r m a t ( "%s : ␣ e n t e r e d ␣ push ( ) \ n" , name ) ; w a i t F o r N o t F u l l ( ) ;

System . ou t . f o r m a t ( "%s : ␣ can ␣ push ( ) \ n" , name ) ; c u r r e n t ++;

d a t a [ c u r r e n t ] = number ;

System . ou t . f o r m a t ( "%s ␣ pushed ␣%d␣ t o ␣[%d ] \ n" , name , number , c u r r e n t ) ; n o t i f y A l l ( ) ;

System . ou t . f o r m a t ( "%s : ␣ ended ␣ push ( ) \ n" , name ) ; }

public synchronized i n t pop ( ) throws I n t e r r u p t e d E x c e p t i o n {

S t r i n g name = Thread . c u r r e n t T h r e a d ( ) . getName ( ) ; System . ou t . f o r m a t ( "%s : ␣ e n t e r e d ␣ pop ( ) \ n" , name ) ; waitForNotEmpty ( ) ;

System . ou t . f o r m a t ( "%s : ␣ can ␣ pop \n" , name ) ; i n t v a l u e = d a t a [ c u r r e n t ] ;

System . ou t . f o r m a t ( "%s : ␣ popped ␣%d␣ from ␣[%d ] \ n" , name , v a l u e , c u r r e n t ) ; c u r r e n t −−;

n o t i f y A l l ( ) ;

System . ou t . f o r m a t ( "%s : ␣ ended ␣ pop ( ) \ n" , name ) ; return v a l u e ;

}

private synchronized void waitForNotEmpty ( ) throws I n t e r r u p t e d E x c e p t i o n {

(5)

while ( c u r r e n t ==−1) {

System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ i s ␣ w a i t i n g ␣ t o ␣ pop " ) ;

w a i t ( ) ; }

}

private synchronized void w a i t F o r N o t F u l l ( ) throws I n t e r r u p t e d E x c e p t i o n {

while ( c u r r e n t==c a p a c i t y −1) {

System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ i s ␣ w a i t i n g ␣ t o ␣ push " ) ;

w a i t ( ) ; }

} }

c l a s s S t a c k P u s h e r extends Thread { W a i t i n g S t a c k s t a c k ;

i n t v a l u e = 0 ;

public S t a c k P u s h e r ( W a i t i n g S t a c k ws ) { s t a c k = ws ;

}

public void run ( ) { try {

while ( true ) { s l e e p ( 1 0 0 ) ;

s t a c k . push(++v a l u e ) ; y i e l d ( ) ;

} }

catch ( I n t e r r u p t e d E x c e p t i o n e ) {

System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ i n t e r r u p t e d " ) ;

} } }

c l a s s StackPopper extends Thread { W a i t i n g S t a c k s t a c k ;

public StackPopper ( W a i t i n g S t a c k ws ) { s t a c k = ws ;

}

public void run ( ) { try {

(6)

while ( true ) { s t a c k . pop ( ) ; y i e l d ( ) ; }

}

catch ( I n t e r r u p t e d E x c e p t i o n e ) {

System . o u t . p r i n t l n ( Thread . c u r r e n t T h r e a d ( ) . getName ( ) + " ␣ i n t e r r u p t e d " ) ;

} } }

public c l a s s WaitingStackDemo {

public s t a t i c void main ( S t r i n g [ ] a r g s ) throws E x c e p t i o n { W a i t i n g S t a c k ws = new W a i t i n g S t a c k ( 1 0 ) ;

S t a c k P u s h e r pu = new S t a c k P u s h e r ( ws ) ; StackPopper po1 = new StackPopper ( ws ) ; StackPopper po2 = new StackPopper ( ws ) ; StackPopper po3 = new StackPopper ( ws ) ; pu . s t a r t ( ) ;

po1 . s t a r t ( ) ; po2 . s t a r t ( ) ; po3 . s t a r t ( ) ;

Thread . s l e e p ( 1 0 0 0 ) ; pu . i n t e r r u p t ( ) ; po1 . i n t e r r u p t ( ) ; po2 . i n t e r r u p t ( ) ; po3 . i n t e r r u p t ( ) ; }

}

3 Bar mleczny "Prawo dżungli"

Rozważ producenta i konsumenta na przykładzie baru mlecznego wydającego posiłki wiecznie głodnym klientom. Producentem jest kucharz umieszczający dania na ladzie, konsumentami są klienci przebywający w barze. Wiecznie głod- ni klienci, których liczba n jest stała, konsumują wydawane potrawy na zasadzie

"kto pierwszy ten lepszy". Zaimplementuj powyższy przykład przy użyciu wąt- ków. Po zakończeniu programu wypisz ile potraw zjadł każdy z klientów.

Cytaty

Powiązane dokumenty

[r]

Nauczyciel zaprasza uczniów do dalszej pracy z wykorzystaniem metody metaplanu, która pozwoli ocenić, dlaczego tak jest w naszym kraju i co należy zrobić, aby zmienić taką

Uzasadnić, że przestrzeń liniowa wszystkich wielomianów (rzeczywistych bądź ze- spolonych) nie jest przestrzenią Banacha w żadnej

Pokazać, że wtedy całą przestrzeń można zapisać w postaci sumy mnogościowej dwu rozłącznych, gęstych i wypukłych

Zbieżność i granica nie zależą od pominięcia lub zmiany skończe- nie wielu początkowych wyrazów

Udowodnić, że średnia arytmetyczna tych liczb jest równa n+1 r

Zastanów si¦, jak wygl¡da twierdzenie o arytmetyce granic, gdy s¡ one niewªa±ciwe.. Jego granica

Utrata zwi¸ azk´ ow fazowych (tzw. koherencji) zredukowanego opera- tora stanu w wyniku ewolucji uk ladu rozszerzonego jest nazywana dekoherencj¸