Vous trouverez ci-dessous le code dans lequel un Thread
entre un bloc synchronisé, attend 5 secondes, puis se ferme. J'ai démarré deux Thread
instances simultanément.
L'attente était que l'un des threads posséderait le verrou sur l'objet synchronisé et l'autre attendrait. Après 5 secondes, lorsque le propriétaire du verrou se ferme, le thread en attente s'exécutera.
Mais, en réalité, les deux threads exécutent le bloc synchronisé simultanément et sortent en même temps.
Production attendue:
Thread-X <timeX> received the lock.
Thread-X <timeX+5s> exiting...
Thread-Y <timeY> received the lock.
Thread-Y <timeY+5s> exiting...
Sortie réelle:
Thread-X <time> received the lock.
Thread-Y <time> received the lock.
Thread-X <time+5s> exiting...
Thread-Y <time+5s> exiting...
Est-ce que j'ai râté quelque chose?
import Java.text.SimpleDateFormat;
import Java.util.Date;
public class Test2 {
public static void main(String[] args) {
MyRunnable m = new MyRunnable();
Thread t = new Thread(m);
Thread t1 = new Thread(m);
t.start();
t1.start();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
synchronized (this) {
try {
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = new Date(System.currentTimeMillis());
System.out.println(Thread.currentThread().getName() + " " + formatter.format(date) + " received the lock.");
wait(5000);
date = new Date(System.currentTimeMillis());
System.out.println(Thread.currentThread().getName() + " " + formatter.format(date) + " exiting...");
} catch(InterruptedException ie) {}
}
}
}
La réponse se trouve dans Java.lang.Object.wait (long) dont la documentation dit:
[...] Cette méthode force le thread en cours (appelez-le T) à se placer dans l'attente définie pour cet objet, puis à abandonner toutes les revendications de synchronisation relatives à cet objet . [...]
Utilisation
Thread.sleep(5000);
Fait suspendre temporairement l'exécution du thread en cours d'exécution pendant le nombre de millisecondes spécifié, sous réserve de la précision et de l'exactitude des temporisateurs et programmateurs du système. Le fil ne perd pas la propriété des moniteurs.
La citation suivante tirée de Oracle Tutorials explique la situation:
Lorsque
wait
est appelé, le thread libère le verrou et suspend l'exécution.
De plus, un seul thread peut exécuter un bloc synchronized
gardé par le même objet! L'appel de wait
dans votre exemple libère le verrou, permettant ainsi à un autre thread d'acquérir le verrou.