(Révisé après une réflexion plus approfondie)
Pour l'exemple présenté ci-dessus, vous pouvez vous en sortir en déclarant votre static int comme volatile, comme l'a suggéré Punkers.
Dans le cas général cependant - par exemple si votre variable statique était un objet avec un état mutable ...
La méthode d'instance synchronisée signifie que seul le thread détenant le verrou objet-instance est autorisé à progresser dans cette méthode de cette instance de la classe A, et que lorsque le thread termine dans la méthode et libère le verrou, tout autre thread entrant dans un bloc synchronisé utilisant le même verrou "verra" les modifications que vous avez apportées.
Elle le fait no empêcher que des modifications soient apportées à la variable statique par un autre thread qui :
- assigne une nouvelle valeur à la variable statique directement depuis l'extérieur de la classe A (la variable est publique !)
- appelle une méthode statique de la classe A (synchronisée ou non) qui réassigne la variable statique, car elle utilisera un verrou différent
- appelle une méthode d'instance non synchronisée de la classe A
L'utilisation de méthodes synchronisées est généralement un peu dangereuse - elles peuvent conduire à des blocages parce que le verrou peut être pris à l'extérieur par un autre code qui utilise votre classe/instance comme cible d'un bloc synchronisé :
synchronized (objectOfTypeA) { ... } // takes the instance lock
ou
synchronized (A.getClass()) { ... } // takes the class lock
Une meilleure approche pourrait être de rendre la variable statique privée, d'ajouter une variable locale privée à utiliser comme verrou (afin qu'elle ne puisse pas être verrouillée en externe), et d'utiliser le verrou local privé dans des blocs synchronisés dans vos méthodes :
public class A {
private static int reg_no = 100;
private static Object lock = new Object();
public void registration(){
synchronized(lock) {
reg_no = some operation...
}
}
public static int getRegNo() {
synchronized(lock) {
return reg_no;
}
}
}