web-dev-qa-db-fra.com

Deux threads exécutant un bloc synchronisé simultanément

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) {}
        }
    }
}
47
somnathchakrabarti

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 . [...]

60
Markus

Utilisation

Thread.sleep(5000);

JavaDocs for Thread.sleep:

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.

32
Selindek

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.

13
Oleksandr Pyrohov