Ludzie pragną czasami się rozstawać, żeby móc tęsknić, czekać i cieszyć się z powrotem.
s e t (0 , 1) ;
8
k . s e t (1 , 1) ;
9
}
10
11
public void run ( ) {
12
13
mojNum = ThreadID . get ( ) ;
14
15
while ( true ) {
16
17
// s e k c j a l o k a l n a
18
try {
19
Thread . s l e e p ( ( long ) (2500 ∗ Math . random ( ) ) ) ;
20
} catch ( InterruptedException e ) {
21
}
22
23
// protok ó ª wst ¦ pny
24
k . s e t (mojNum, 0) ;
25
while ( k . get (1 − mojNum) == 0) {
26
k . s e t (mojNum, 1) ;
27
Thread . y i e l d ( ) ;
28
k . s e t (mojNum, 0) ;
29
}
30
// s e k c j a k r y t y c z n a
31
System . out . p r i n t l n ( "W¡ tek " + mojNum + " s t a r t SK" ) ;
32
try {
1.3. Problem wzajemnego wykluczania
21
33
Thread . s l e e p ( ( long ) (2100 ∗ Math . random ( ) ) ) ;
34
} catch ( InterruptedException e ) {
35
}
36
System . out . p r i n t l n ( "W¡ tek " + mojNum + " stop SK" ) ;
37
// protok ó ª ko«cowy
38
k . s e t (mojNum, 1) ;
39
}
40
}
41
42
public Main ( ) {
43
}
44
45
public static void main ( S t r i n g [ ] args ) {
46
47
new Thread (new Main ( ) , "0" ) . s t a r t ( ) ;
48
new Thread (new Main ( ) , "1" ) . s t a r t ( ) ;
49
}
50
}
Poprawnym rozwiązaniem problemu jest algorytm Dekkera, który można
uznać za połączenie próby pierwszej i czwartej (listing 1.19).
Listing 1.19. Problem wzajemnego wykluczania – algorytm Dekkera
1
2
3
public class Dekker implements Runnable {
4
5
static AtomicIntegerArray k = new AtomicIntegerArray ( 2 ) ;
6
static volatile int c z y j a K o l e j = 0 ;
7
int mojNum ;
8
9
static {
10
k . s e t (0 , 1) ;
11
k . s e t (1 , 1) ;
12
}
13
14
public void run ( ) {
15
16
mojNum = ThreadID . get ( ) ;
17
18
while ( true ) {
19
20
// s e k c j a l o k a l n a
21
try {
22
Thread . s l e e p ( ( long ) (2500 ∗ Math . random ( ) ) ) ;
23
} catch ( InterruptedException e ) {
24
}
25
26
// protok ó ª wst ¦ pny
27
k . s e t (mojNum, 1) ;
22
1. Podstawowe pojęcia dotyczące współbieżności
28
while ( k . get (1 − mojNum) == 1) {
29
30
i f ( c z y j a K o l e j != mojNum) {
31
k . s e t (mojNum, 0) ;
32
while ( c z y j a K o l e j != mojNum) {
33
Thread . y i e l d ( ) ;
34
}
35
k . s e t (mojNum, 1) ;
36
}
37
}
38
39
// s e k c j a k r y t y c z n a
40
System . out . p r i n t l n ( "W¡ tek " + mojNum + " s t a r t SK" ) ;
41
try {
42
Thread . s l e e p ( ( long ) (1000 ∗ Math . random ( ) ) ) ;
43
} catch ( InterruptedException e ) {
44
}
45
System . out . p r i n t l n ( "W¡ tek " + mojNum + " stop SK" ) ;
46
47
// protok ó ª ko«cowy
48
c z y j a K o l e j = 1 − mojNum ;
49
k . s e t (mojNum, 0) ;
50
}
51
}
52
53
public Dekker ( ) {
54
}
55
56
public static void main ( S t r i n g [ ] args ) {
57
58
new Thread (new Dekker ( ) , "0" ) . s t a r t ( ) ;
59
new Thread (new Dekker ( ) , "1" ) . s t a r t ( ) ;
60
}
61
}
1.4. Zadania
1.4.1. Nazywanie wątków w przypadku dziedziczenia po klasie
Thread
Zdefiniuj klasę wątku jako rozszerzenie klasy Thread. Utwórz trzy wątki
nadając im nazwy: Watek1, Watek2 oraz Watek3. Wystartuj wszystkie trzy
wątki. Niech każdy z nich wypisze swoją nazwę.
1.4. Zadania
23
1.4.2. Nazywanie wątków w przypadku rozszerzania interfejsu
Runnable
Zdefiniuj klasę wątku jako implementację interfejsu Runnable. Utwórz
trzy wątki nadając im nazwy: Zadanie1, Zadanie2 oraz Zadanie3. Uruchom
tak utworzone wątki. Niech każdy wątek, łącznie z wątkiem głównym, wy-
pisze swoją nazwę.
1.4.3. Algorytm Dekkera
Zaimplementuj algorytm Dekkera rozwiązujący problem wzajemnego
wykluczania dla dwóch wątków, ale bez użycia klasy AtomicIntegerArray.
Posłuż się poniższym pseudokodem [3, 5].
varchce1 : boolean := false ;
chce2 : boolean := f a l s e ;
kto_czeka : 1 . . 2 := 1 ;
thread w1 ;
thread w2 ;
begin
begin
while true do
while true do
begin
begin
s e k c j a l o k a l n a ;
s e k c j a l o k a l n a ;
chce1 := true ;
chce2 := true ;
while ( chce2 ) do
while ( chce1 ) do
begin
begin
i f ( kto_czeka = 1)
i f ( kto_czeka = 2)
begin
begin
chce1 := f a l s e ;
chce2 := f a l s e ;
while ( kto_czeka = 1)
while ( kto_czeka = 2)
do
do
begin
begin
// nie r ób nic
// nie r ób nic
end ;
end ;
chce1 := true ;
chce2 := true ;
end ;
end ;
end ;
end ;
s e k c j a krytyczna ;
s e k c j a krytyczna ;
kto_czeka := 1 ;
kto_czeka := 2 ;
chce1 := f a l s e ;
chce2 := f a l s e ;
end ;
end ;
end ;
end ;
24
1. Podstawowe pojęcia dotyczące współbieżności
1.4.4. Algorytm Dorana-Thomasa
Zaimplementuj algorytm Dorana-Thomasa rozwiązujący problem wza-
jemnego wykluczania dla dwóch wątków. Posłuż się poniższym pseudoko-
dem [3].
varchce1 : boolean := false ;
chce2 : boolean := f a l s e ;
kto_czeka : 1 . . 2 := 1 ;
thread w1 ;
thread w2 ;
begin
begin ;
while true do
while true do
begin
begin
s e k c j a l o k a l n a ;
s e k c j a l o k a l n a ;
chce1 := true ;
chce2 := true ;
i f ( chce2 ) do
i f ( chce1 ) do
begin
begin
i f ( kto_czeka = 1)
i f ( kto_czeka = 2)
begin
begin
chce1 := f a l s e ;
chce2 := f a l s e ;
while ( kto_czeka = 1)
while ( kto_czeka = 2)
do
do
begin
begin
// nie r ób nic
// nie r ób nic
end ;
end ;
chce1 := true ;
chce2 := true ;
end ;
end ;
while ( chce2 ) do
while ( chce1 ) do
begin
begin
// nie r ób nic
// nie r ób nic
end ;
end ;
end ;
end ;
s e k c j a krytyczna ;
s e k c j a krytyczna ;
chce1 := f a l s e ;
chce2 := f a l s e ;
kto_czeka := 1 ;
kto_czeka := 2 ;
end ;
end ;
end ;
end ;
1.4.5. Algorytm Petersona
Zaimplementuj algorytm Petersona rozwiązujący problem wzajemnego
wykluczania dla dwóch wątków. Posłuż się poniższym pseudokodem [3, 5].
1.4. Zadania
25
varchce1 : boolean := false ;
chce2 : boolean := f a l s e ;
kto_czeka : 1 . . 2 := 1 ;
thread w1 ;
thread w2 ;
begin
begin
while true do
while true do
begin
begin
s e k c j a l o k a l n a ;
s e k c j a l o k a l n a ;
chce1 := true ;
chce2 := true ;
kto_czeka := 1 ;
kto_czeka := 2 ;
while
while
chce2 and ( kto_czeka = 1)