Problemy ze
współbieżnością
Jeżeli kilka wątków może jednocześnie działać na tym samym
obiekcie wówczas mogą pojawiać się pewne nieprzewidywane i
często niepożądane efekty.
Rozważmy następujący przykład:
class Balance {
private int number = 0;
public int balance() {
number++;
number--;
return number;
}
}
Wydaje się, że jakiekolwiek wielokrotne wywołanie metody
balance() na rzecz dowolnego obiektu klasy Balance zawsze zwróci
0. Okazuje się jednak, że wielokrotne wywołanie tej metody na rzecz
tego samego obiektu może dawać inny wynik. Sytuacja taka może powstać
wtedy gdy działający wątek wykona instrukcję number++ i zostanie
wywłaszczony. W efekcie number=1.
Przykład:
Aplet gdzie w kilku różnych
wątkach wielokrotnie wywoływana jest metoda balance() na rzecz tego
samego obiektu. Jeżeli wynik zwracany przez balance() będzie
różny od zera to wątek jest przerywany.
Aplet
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
class Balance {
private int number = 0;
public int balance() {
number++;
number--;
return number;
}
}
class BalanceThread extends Thread {
private Balance b; //
referencja do obiektu klasy Balance
private int count; //
liczba pwotórzeń pętli w metodzie run
public BalanceThread(String
name, Balance b, int count) {
super(name);
this.b = b;
this.count = count;
start();
}
public void run() {
int wynik = 0;
// synchronized(b) {
for
(int i = 0; i < count; i++) {
wynik = b.balance();
if (wynik != 0) break;
}
// }
Thread.currentThread().setName("wynik="+wynik);
}
}
public class BalanceTest extends
Applet implements ActionListener{
int
tnum=5; // liczba wątkow
Button przycisk =
new Button("Start");
TextField t1 = new
TextField("10000000");
Label [] la = new
Label[tnum];
Label status = new
Label("status");
Panel pan = new
Panel();
public void
init(){
add(new Label("#
iteracji"));
add(t1);
t1.addActionListener(this);
add(przycisk);
przycisk.addActionListener(this);
for(int i=0;i<tnum;i++){la[i]=new
Label("label "+i); pan.add(la[i]);}
pan.setLayout(new
GridLayout(5,1));
add(pan);
add(status);
} // koniec init
public void
actionPerformed(ActionEvent e){
int count=10000000;
if(e.getSource()==t1){count=Integer.parseInt(t1.getText());
}
else{
status.setText("liczę");
// Tworzymy obiekt klasy
balance
Balance b = new
Balance();
// Tworzymy i
uruchamiamy wątki
Thread[] thread =
new Thread[tnum];
for (int i = 0; i
< tnum; i++)
thread[i] = new BalanceThread("W"+(i+1), b, count);
// czekaj na
zakończenie wszystkich wątków
try {
for
(int i = 0; i < tnum; i++) {thread[i].join();
la[i].setText(thread[i].getName());
thread[i]=null;}
} catch
(InterruptedException exc) {
System.exit(1);
}
status.setText("koniec");
}//koniec if'a
} // koniec
actionPerformed
}
//koniec BalanceTest