5 wątków puszczanych jednocześnie. Współdzielą jeden obiekt. Każdy z nich najpierw pobiera atrybut współdzielonego obiektu, a następnie zwiększa jego wartość o 1 i nadpisuje. Czynność powtórzona 20 krotnie, więc obiekt zmaglowany przez 5 wątków powinien skończyć z wartością atrybutu większą o 100.
Jak mniemam zdarza się, że np. wątek A pobierze wartość 50
i zanim zapisze ją jako 51
wątek B też pobierze 50
i zapisze 51
. Gdy takie przypadki wystąpią to ostateczna wartość atrybutu będzie powiększona o < 100. To mnie nie dziwi. Ale czemu zdarza się, że ostateczna wartość atrybutu jest powiększona o > 100 ?
Drugie pytanie: jak to nareperowac. Dodawanie synchronized
do metod nie pomaga...
public class App {
public static void main(String[] args) throws InterruptedException {
Counter c1 = new Counter();
Thread th1 = new Thread(new CounterThread(c1), "thread_1");
Thread th2 = new Thread(new CounterThread(c1), "thread_2");
Thread th3 = new Thread(new CounterThread(c1), "thread_3");
Thread th4 = new Thread(new CounterThread(c1), "thread_4");
Thread th5 = new Thread(new CounterThread(c1), "thread_5");
th1.start();
th2.start();
th3.start();
th4.start();
th5.start();
th1.join();
th2.join();
th3.join();
th4.join();
th5.join();
System.out.println("===");
System.out.println(c1.getNumber());
System.out.println("===");
}
}
public class CounterThread implements Runnable {
private Counter counter;
public CounterThread(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i<100; i++) {
synchronized(this) {
int numberToSet = counter.getNumber();
System.out.println(Thread.currentThread().getName() + ": " + numberToSet);
counter.setNumber(numberToSet + 1);
}
}
}
}
public class Counter {
private int number;
private boolean isLocked;
public synchronized int getNumber() {
this.isLocked = true;
return number;
}
public synchronized void setNumber(int numberToSet) {
this.number = numberToSet;
this.isLocked = false;
}
}