/*
This should always produce 0 as output since all three methods increment(), decrement(), value() are thread safe(synchronized). but it is returning 1
*/
class Counter implements Runnable {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
public void run() {
try {
this.increment();
Thread.sleep(1000);
this.decrement();
Thread.sleep(1000);
this.increment();
Thread.sleep(1000);
this.decrement();
Thread.sleep(1000);
}
catch (InterruptedException e){
return;
}
}
public static void main(String args[]) throws InterruptedException {
Counter c = new Counter();
new Thread(c).start();
new Thread(c).start();
System.out.println(c.value());
}
}
Répondre
Vous lisez la valeur avant que les threads aient terminé l'exécution, donc il peut être bien différent de zéro.
Vous n'attendez pas l'exécution des threads, le résultat est que la valeur de c est imprimée à tout moment à la seconde. Je parie que si vous essayé 1000 fois, il y aurait des moments où il n'a pas été 1.
IBM a un tutoriel juste sur la situation que vous rencontrez: http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzahw/rzahwex3rx.htm
Il n'y a rien à contrôler quand la principale le thread appelle value()
. Il s'exécutera dès qu'il pourra acquérir un verrou sur c
, même si les autres threads sont toujours en cours d'exécution.
Si vous souhaitez attendre que les threads soient terminés, appelez le join()
.
Comme tout le monde a dit que vous devez vous assurer que les bandes de roulement ont terminé l'exécution, pour ce faire, vous devez appeler join. par exemple
public static void main(String args[]) throws InterruptedException {
Counter c = new Counter();
Thread t1 = new Thread(c).start();
Thread t2 = new Thread(c).start();
t1.join();
t2.join();
System.out.println(c.value());
}
qui devrait fonctionner correctement