J'ai du mal à comprendre comment la synchronisation fonctionne sur deux méthodes distinctes du même objet. J'ai une classe, avec deux méthodes d'instance qui sont déclarées synchronisées. Trois threads accèdent aux deux méthodes synchronisées de cet objet, mais le résultat est inattendu. Les threads accèdent indifféremment aux deux méthodes. Ils n'attendent pas que le verrou de l'objet entier soit libéré. Voici l'exemple :
public class ThreadSafeCounterSameMonitor2 {
private int value;
public synchronized int getValue() {
return this.value;
}
public synchronized void setValue(int value) {
this.value = value;
}
public static void main(String[] args) {
ThreadSafeCounterSameMonitor2 nts = new ThreadSafeCounterSameMonitor2();
Thread th1 = new Thread(new Runnable() {
public void run() {
nts.setValue(5);
System.out.println("Thread Id " + Thread.currentThread().getId() + ", expected value is 5, value=" + nts.getValue());
}
});
Thread th2 = new Thread(new Runnable() {
public void run() {
nts.setValue(10);
System.out.println("Thread Id " + Thread.currentThread().getId() + ", expected value is 10, value="
+ nts.getValue());
}
});
Thread th3 = new Thread(new Runnable() {
public void run() {
nts.setValue(15);
System.out.println("Thread Id " + Thread.currentThread().getId() + ", expected value is 15, value="
+ nts.getValue());
}
});
th1.start();
th2.start();
th3.start();
}
}
Le résultat que j'obtiens est surprenant :
Thread Id 13, expected value is 15, value=15.
Thread Id 12, expected value is 10, value=15.
Thread Id 11, expected value is 5, value=15.
Donc, là où je m'attendais à 10, il y en a 15. Là où j'attendais 5, j'obtiens encore 15.
J'avais cru comprendre que toutes les méthodes synchronisées du moniteur seraient verrouillées en cas d'accès par un thread. Mais elles ne le sont pas. Dans la même méthode run() d'un thread, je définis une valeur, puis je la récupère et je reçois une autre valeur, modifiée par un autre thread.
J'ai souvent lu quelque chose comme "Une méthode synchronisée acquiert un verrou implicite sur cette référence", mais ce n'est clairement pas vrai, pas même pour toutes les méthodes synchronisées dans le même moniteur. Ou est-ce que je fais quelque chose de mal dans le code ?
Ma question est la suivante : comment puis-je vraiment verrouiller l'ensemble des méthodes synchronisées de l'objet ? Connaissez-vous un tutoriel qui explique bien ce concept ?